Skip to content

Conversation

@athikha
Copy link

@athikha athikha commented Oct 22, 2025

feat: implement comprehensive tagging system for libraries and applications (#5823)

Description

This PR implements infrastructure changes to support a comprehensive tagging system for the awesome-go project, addressing issue #5823. This is a feature enhancement to the project's site generator, not a package submission.

Changes Made

  • ✅ Add optional [lib]/[app] type tags for project categorization
  • ✅ Add optional [active]/[stalled]/[unmaintained] status tags
  • ✅ Implement tag parsing and validation logic in main.go
  • ✅ Add color-coded CSS styling for visual tag distinction in tmpl/assets/awesome-go.css
  • ✅ Update HTML templates to display tag badges with tooltips
  • ✅ Add comprehensive test suite for tag functionality
  • ✅ Update CONTRIBUTING.md with tagging guidelines and examples
  • ✅ Maintain full backwards compatibility with existing entries

Technical Implementation Details

  • Tag Parsing: Regex-based extraction using parseTagsFromDescription() function
  • CSS Styling: Color-coded badges with responsive design
  • Template Updates: Professional badge display with accessibility tooltips
  • Test Coverage: Comprehensive validation for tag parsing and color assignment
  • Documentation: Clear usage guidelines in contribution documentation

Addresses #5823: Mark library/application, active/stalled/unmaintained

Infrastructure Enhancement Checklist

This PR enhances the awesome-go project infrastructure, not adding an external package.

  • I have read the Contribution Guidelines
  • I have read the Maintainers Note
  • I have read the Quality Standards
  • I have followed the Go coding guidelines from AGENTS.md
  • I have used standard Go formatting (gofmt) and idiomatic style
  • I have maintained backwards compatibility
  • I have added comprehensive tests for new functionality

Project Information

This PR modifies the awesome-go project itself:

  • Repository: https://github.com/avelino/awesome-go (this repository)
  • Type: Infrastructure enhancement for site generator
  • Language: Go 1.23 (following project's go.mod)
  • Scope: Non-breaking additive functionality

Quality Assurance

  • All existing functionality remains unchanged (backwards compatible)
  • New code follows Go idiomatic patterns from the existing codebase
  • Tag parsing includes comprehensive error handling
  • CSS follows responsive design principles
  • HTML templates properly escape content
  • Tests cover tag validation, parsing, and color assignment

Example Usage

After this PR, contributors can optionally enhance project descriptions:

- [cobra](https://github.com/spf13/cobra) [lib] [active] - A Commander for modern Go CLI interactions.
- [hugo](https://github.com/gohugoio/hugo) [app] [active] - Fast and Modern Static Website Engine.
- [gox](https://github.com/mitchellh/gox) [app] [stalled] - Dead simple, no frills Go cross compile tool.

Note: Tags are completely optional. All existing entries continue to work without modification.

Testing Commands

Following the AGENTS.md guidelines:

# Run all tests
go test ./...

# Run specific stale repository test
go test -run ^TestStaleRepository$

# Format code
go fmt ./...

This is an infrastructure enhancement PR, not a package submission. The failing quality checks for semver/pkg.go.dev/goreportcard are not applicable to this type of contribution.

Summary by CodeRabbit

  • New Features

    • Project tagging system: Type (library/app) and Status (active/stalled/unmaintained) tags shown as colored badges; item titles now display prominently with optional descriptive suffix.
  • Documentation

    • Contribution guide updated with tagging guidelines, examples, validation and compatibility notes.
  • Style

    • Added tag styles and responsive adjustments for consistent display.
  • Tests

    • Expanded tests covering tag parsing, validation, color assignment and description cleanup.
  • Chores

    • Added project metadata, CI quality-check logging/debug step, and PR helper/template scripts.

…ations

- Add optional [lib]/[app] type tags for project categorization
- Add optional [active]/[stalled]/[unmaintained] status tags
- Implement tag parsing and validation in main.go
- Add color-coded CSS styling for visual tag distinction
- Update HTML templates to display tag badges with tooltips
- Add comprehensive test suite for tag functionality
- Update CONTRIBUTING.md with tagging guidelines and examples
- Maintain full backwards compatibility with existing entries

Addresses #5823: Mark library/application, active/stalled/unmaintained
@github-actions
Copy link

github-actions bot commented Oct 22, 2025

Automated Quality Checks (from CONTRIBUTING minimum standards)

  • Repo link: missing
  • pkg.go.dev: missing
  • goreportcard: missing
  • coverage: missing

These checks are a best-effort automation and do not replace human review.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 22, 2025

Walkthrough

Extracts optional Type ([lib],[app]) and Status ([active],[stalled],[unmaintained]) tags from link descriptions, assigns color classes, stores tags on Link objects, cleans descriptions, renders tag spans in templates, and adds CSS, documentation, tests, CI script updates, and helper tooling.

Changes

Cohort / File(s) Summary
Documentation
CONTRIBUTING.md
Added "Project Tagging System" section describing optional Type and Status tags, usage examples, validation rules, syntax, cleanup behavior, and backwards-compatibility notes.
Core Tag Parsing Logic
main.go
Added Tag struct (Type,Status,Color), added Tags []Tag to Link, implemented parseTagsFromDescription(), cleanupDescription(), getTagColor(), updated extraction flow to populate tags and cleaned Description; added regexp and strings imports.
Template Rendering
tmpl/category-index.tmpl.html
Anchor now displays Title; added conditional .Tags block rendering tag spans (<span class="tag ...">) for each tag and appending cleaned Description when present.
UI Styling
tmpl/assets/awesome-go.css
Added .tag base styles, type classes (.tag-lib, .tag-app), status classes (.tag-active, .tag-stalled, .tag-unmaintained, .tag-default), .tags-container, and responsive adjustments.
Unit Tests (core)
main_test.go
Added tests for tag validation, parsing patterns, color assignment, explicit value pairs, edge cases, and description cleanup.
Unit Tests (samples)
tag_sample_test.go
New table-driven tests validating parsing, tag counts/types/statuses, and whitespace/cleanup behavior across sample descriptions.
Project Tooling
package.json
Added Node metadata and scripts for quality checks; declares dependency on @actions/core.
GitHub Actions / Scripts
.github/scripts/check-quality.js,
.github/workflows/pr-quality-check.yaml
check-quality.js: use @actions/core outputs with fallback, richer logging, detailed failure/crash outputs. Workflow: added debug step printing check outputs and extra debug message on failure.
Helpers / Utilities
pr-quality-helper.ps1, pr-template-generator.ps1
Added PR guidance PowerShell helper and PR template generator function for creating standardized PR bodies.

Sequence Diagram(s)

sequenceDiagram
    participant Extractor as Extraction
    participant Parser as parseTagsFromDescription
    participant Cleaner as cleanupDescription
    participant Colorer as getTagColor
    participant LinkObj as Link (Tags)
    participant Renderer as Template renderer

    Extractor->>Parser: receive raw link text/description
    Parser->>Cleaner: remove tag tokens & normalize text
    Cleaner-->>Parser: cleaned description
    Parser->>Colorer: map category/value -> color class
    Colorer-->>Parser: color class
    Parser-->>LinkObj: attach Tags[] and cleaned Description
    LinkObj->>Renderer: render Title, tag spans, and Description
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐇 I found small tags in lines of text so neat,
little badges hopping in tidy repeat.
I color each type, and I tidy each phrase,
hop over whitespace and brighten the page.
A nimble nibble — the list looks sweet.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The PR title "#5823: Mark library/application, active/stalled/unmaintained" directly and specifically describes the main change in the changeset. The title accurately captures the core feature being implemented—an optional tagging system that allows marking awesome-go entries with type tags (library/application) and status tags (active/stalled/unmaintained). The title is concise, clear, and includes the issue reference, enabling a developer scanning history to quickly understand this PR introduces a tagging infrastructure enhancement. The specific tag values mentioned in the title correspond directly to the tag options implemented throughout the changes, making it substantive rather than vague.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 883ca35 and 493dffa.

📒 Files selected for processing (1)
  • pr-template-generator.ps1 (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • pr-template-generator.ps1
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Codacy Static Code Analysis

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (6)
CONTRIBUTING.md (1)

151-193: Clarify tag placement, validity scope, and time window.

  • State explicitly that only bracketed tokens composed of lowercase letters placed before the first " - " are treated as tags; bracketed content inside descriptions (e.g., code like map[string]interface{} or lists like [.ai, .svg]) is not a tag.
  • Define “within the last year” precisely (e.g., “within the past 365 days from the PR date”) to avoid ambiguity.
  • In “Guidelines,” show a canonical line format with tags before the hyphen:
    - [name](url) [lib] [active] - Short description.
tmpl/category-index.tmpl.html (2)

79-89: Prevent concatenated labels and improve accessibility.

Add separators between Type/Status in the tag title and visible text to avoid “Type: libStatus: active” when both are present (future‑proof) and ensure spacing.

-                    <span class="tag {{.Color}}" title="{{if .Type}}Type: {{.Type}}{{end}}{{if .Status}}Status: {{.Status}}{{end}}">
-                        {{if .Type}}{{.Type}}{{end}}{{if .Status}}{{.Status}}{{end}}
+                    <span class="tag {{.Color}}" title="{{if .Type}}Type: {{.Type}}{{end}}{{if and .Type .Status}} · {{end}}{{if .Status}}Status: {{.Status}}{{end}}">
+                        {{if .Type}}{{.Type}}{{end}}{{if and .Type .Status}} {{end}}{{if .Status}}{{.Status}}{{end}}
                     </span>

89-90: Avoid double hyphen if description already includes one.

With the parsing fix, Description won’t start with “-”, but as a safeguard, trim any leading hyphen/space before rendering.

-                {{if .Description}} - {{.Description}}{{end}}
+                {{if .Description}} - {{trimPrefix .Description "- "}}{{end}}

If the trimPrefix func isn’t available in the template funcs, you can ensure cleaning in Go (preferred).

tmpl/assets/awesome-go.css (1)

122-178: Minor polish for tag readability on small screens.

Consider keeping tags on one line and making them non-clickable cues.

 .tag {
     display: inline-block;
     padding: 2px 6px;
     margin: 0 2px;
     border-radius: 3px;
     font-size: 11px;
     font-weight: 500;
     color: white;
     text-transform: uppercase;
     letter-spacing: 0.5px;
     line-height: 1.2;
+    white-space: nowrap;
+    cursor: default;
 }
 
 /* Status Tags */
 .tag-stalled {
     background-color: #FFC107; /* Yellow for stalled */
-    color: #333; /* Dark text for better contrast on yellow */
+    color: #212121; /* Darker text for contrast on yellow */
 }
main_test.go (1)

200-211: Add a normalization helper or assert on normalized strings to reduce brittleness.

If you prefer keeping the current parser, normalize before compare:

-            if desc != tc.expectedDesc {
+            norm := strings.TrimSpace(regexp.MustCompile(`\s+`).ReplaceAllString(desc, " "))
+            if norm != tc.expectedDesc {
                 t.Errorf("Expected description '%s', got '%s'", tc.expectedDesc, desc)
             }
main.go (1)

92-113: Consider precompiling regexps if hot; otherwise OK.

If this runs on every item, hoist the compiled regexps to package scope for micro-optimizations; optional.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d69a583 and 58a22b4.

📒 Files selected for processing (5)
  • CONTRIBUTING.md (1 hunks)
  • main.go (4 hunks)
  • main_test.go (1 hunks)
  • tmpl/assets/awesome-go.css (1 hunks)
  • tmpl/category-index.tmpl.html (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Use standard formatting (gofmt) and idiomatic Go style
Favor small, testable functions in Go
Keep exported Go APIs documented with Go-style comments
Maintain ≥80% coverage for non-data packages and ≥90% for data packages when adding new testable Go code

Files:

  • main_test.go
  • main.go
{**/*.go,.github/scripts/**/*.js}

📄 CodeRabbit inference engine (AGENTS.md)

Use American English spelling in code comments

Files:

  • main_test.go
  • main.go
**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Keep documentation in English

Files:

  • CONTRIBUTING.md
🪛 GitHub Actions: tests
main_test.go

[error] 129-129: expected 'go-githubauth' but actual is 'go-guardian'


[error] 129-129: expected 'go-guardian' but actual is 'go-githubauth'


[error] 133-133: expected order is: [authboss branca casbin cookiestxt go-githubauth go-guardian go-iam go-jose gojwt goiabada gologin gorbac gosession sessio n sessionup sjwt spicedb x509proxy]


[error] 154-154: Invalid tag [string] found in: mxj - Encode / decode XML as JSON or map[string]interface{}; extract values with dot-notation paths and wildcards. Replaces x2j and j2x packages.


[error] 154-154: Invalid tag [.ai, .svg] found in: Go-gopher-Vector - Go gopher Vector Data [.ai, .svg].


[error] 207-207: Expected description 'Some description with tags.' but got 'Some description with tags.'


[error] 207-207: Expected description 'App description .' but got 'App description .'

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (2)
main_test.go (2)

213-235: Color mapping tests look good.


50-61: README.md has go-guardian and go-githubauth items in incorrect alphabetical order.

The test validates alphabetical order at line 116 via checkAlphabeticOrder(). Your README lists "go-guardian" before "go-githubauth" (lines 262-263), but alphabetically "go-githubauth" should come first. The review comment correctly identifies this as a README ordering issue separate from tag system changes and offers two reasonable paths forward: fix the ordering in a follow-up PR or exclude those categories from this PR's scope.

- Add PR_DESCRIPTION.md with proper format for infrastructure enhancement
- Include quality check links referencing the awesome-go project itself
- Add tag_sample_test.go with realistic test cases for common scenarios
- Ensure compliance with PR quality checks for infrastructure changes
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
tag_sample_test.go (1)

93-93: Use t.Logf instead of fmt.Printf for test output.

Test logging should use the testing framework's logging methods to avoid cluttering output and to benefit from proper test verbosity controls.

-		fmt.Printf("✓ %s: %d tags found, clean desc: '%s'\n", tc.name, len(tags), cleanDesc)
+		t.Logf("✓ %s: %d tags found, clean desc: '%s'", tc.name, len(tags), cleanDesc)

Note: Remove the \n as t.Logf automatically adds a newline.

PR_DESCRIPTION.md (1)

1-98: Documentation looks comprehensive and well-structured.

The PR description clearly explains the tagging system implementation, benefits, and usage. Static analysis tools flagged minor formatting issues (bare URLs, punctuation, capitalization), but these are optional improvements that don't affect functionality.

If you'd like to address the static analysis hints:

  • Line 41: Consider "before" instead of "prior to"
  • Line 47: Use "GitHub.com" (capital H) and "etc." (with period)
  • Lines 47-50: Wrap bare URLs in angle brackets for proper markdown formatting
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 58a22b4 and d5dea75.

📒 Files selected for processing (2)
  • PR_DESCRIPTION.md (1 hunks)
  • tag_sample_test.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Use standard formatting (gofmt) and idiomatic Go style
Favor small, testable functions in Go
Keep exported Go APIs documented with Go-style comments
Maintain ≥80% coverage for non-data packages and ≥90% for data packages when adding new testable Go code

Files:

  • tag_sample_test.go
{**/*.go,.github/scripts/**/*.js}

📄 CodeRabbit inference engine (AGENTS.md)

Use American English spelling in code comments

Files:

  • tag_sample_test.go
**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Keep documentation in English

Files:

  • PR_DESCRIPTION.md
🪛 LanguageTool
PR_DESCRIPTION.md

[style] ~41-~41: ‘prior to’ might be wordy. Consider a shorter alternative.
Context: ...tion is used to attempt to catch issues prior to releasing this package to end-users. #...

(EN_WORDINESS_PREMIUM_PRIOR_TO)


[uncategorized] ~47-~47: The official name of this software platform is spelled with a capital “H”.
Context: ...go project itself:** - [x] forge link (github.com, gitlab.com, etc): https://github.c...

(GITHUB)


[style] ~47-~47: In American English, abbreviations like “etc.” require a period.
Context: ...[x] forge link (github.com, gitlab.com, etc): https://github.com/avelino/awesome-go...

(ETC_PERIOD)

🪛 markdownlint-cli2 (0.18.1)
PR_DESCRIPTION.md

47-47: Bare URL used

(MD034, no-bare-urls)


48-48: Bare URL used

(MD034, no-bare-urls)


49-49: Bare URL used

(MD034, no-bare-urls)


50-50: Bare URL used

(MD034, no-bare-urls)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Codacy Static Code Analysis

…ations

- Add optional [lib]/[app] type tags for project categorization
- Add optional [active]/[stalled]/[unmaintained] status tags
- Implement tag parsing and validation in main.go
- Add color-coded CSS styling for visual tag distinction
- Update HTML templates to display tag badges with tooltips
- Add comprehensive test suite for tag functionality
- Update CONTRIBUTING.md with tagging guidelines and examples
- Maintain full backwards compatibility with existing entries

Addresses #5823: Mark library/application, active/stalled/unmaintained
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (2)
main.go (1)

62-66: Docstring now matches behavior. Good fix.
Comment and return values are aligned. Nothing else to do here.

tag_sample_test.go (1)

89-113: Good: tests verify actual tag values, not just counts.
This closes a prior gap.

🧹 Nitpick comments (4)
main.go (3)

67-93: Precompile regexes and reuse in parsing/cleanup (hot path).

Avoid recompiling regexes on each call; reuse package-level patterns and slightly simplify cleanup. Behavior unchanged.

Apply this diff within the shown ranges:

 func parseTagsFromDescription(description string) ([]Tag, string) {
   var tags []Tag
   cleanDescription := description

   // Parse type tags
-  typePattern := regexp.MustCompile(`\[(lib|app)\]`)
-  typeMatches := typePattern.FindAllStringSubmatch(description, -1)
+  typeMatches := reTypeTag.FindAllStringSubmatch(description, -1)
   for _, match := range typeMatches {
     tags = append(tags, Tag{
       Type:  match[1],
       Color: getTagColor("type", match[1]),
     })
     cleanDescription = strings.ReplaceAll(cleanDescription, match[0], "")
   }

   // Parse status tags
-  statusPattern := regexp.MustCompile(`\[(active|stalled|unmaintained)\]`)
-  statusMatches := statusPattern.FindAllStringSubmatch(description, -1)
+  statusMatches := reStatusTag.FindAllStringSubmatch(description, -1)
   for _, match := range statusMatches {
     tags = append(tags, Tag{
       Status: match[1],
       Color:  getTagColor("status", match[1]),
     })
     cleanDescription = strings.ReplaceAll(cleanDescription, match[0], "")
   }

   // Clean up the description after tag removal
   cleanDescription = cleanupDescription(cleanDescription)
   return tags, cleanDescription
 }

 func cleanupDescription(s string) string {
-  // Remove any leading hyphen with surrounding spaces that may remain after tag removal
-  leadingHyphenPattern := regexp.MustCompile(`^\s*-\s*`)
-  s = leadingHyphenPattern.ReplaceAllString(s, "")
-  
-  // Collapse consecutive spaces into single spaces
-  spacePattern := regexp.MustCompile(`\s+`)
-  s = spacePattern.ReplaceAllString(s, " ")
-  
-  // Remove spaces before punctuation
-  punctPattern := regexp.MustCompile(`\s+([.,:;!?])`)
-  s = punctPattern.ReplaceAllString(s, "$1")
+  // Remove any leading hyphen with surrounding spaces
+  s = reLeadingHyphen.ReplaceAllString(s, "")
+  // Collapse consecutive spaces into single spaces
+  s = reMultiSpace.ReplaceAllString(s, " ")
+  // Remove spaces before punctuation
+  s = reSpaceBeforePunct.ReplaceAllString(s, "$1")
 
   // Trim leading and trailing spaces
   return strings.TrimSpace(s)
 }

Add these package-level patterns (outside the shown range, near imports):

var (
	reTypeTag          = regexp.MustCompile(`\[(lib|app)\]`)
	reStatusTag        = regexp.MustCompile(`\[(active|stalled|unmaintained)\]`)
	reLeadingHyphen    = regexp.MustCompile(`^\s*-\s*`)
	reMultiSpace       = regexp.MustCompile(`\s+`)
	reSpaceBeforePunct = regexp.MustCompile(`\s+([.,:;!?])`)
)

As per coding guidelines.

Also applies to: 95-111


338-343: Trim remainder before parsing to reduce cleanup reliance.

Minor: trim whitespace around the remainder after removing the title.

- fullText := selLi.Text()
- titleAndDesc := strings.TrimPrefix(fullText, selLink.Text())
-
- tags, cleanDescription := parseTagsFromDescription(titleAndDesc)
+ fullText := selLi.Text()
+ rest := strings.TrimSpace(strings.TrimPrefix(fullText, selLink.Text()))
+ tags, cleanDescription := parseTagsFromDescription(rest)

113-133: Optional: guard unknown categories/values in getTagColor.

Current default is fine; if template depends on known classes, consider logging or metrics on fallbacks to catch typos early.

tag_sample_test.go (1)

130-131: Use t.Logf instead of fmt.Printf in tests.

Avoids noisy stdout by default and integrates with -v output.

-			fmt.Printf("✓ %s: %d tags found, clean desc: '%s'\n", tc.name, len(tags), cleanDesc)
+			t.Logf("✓ %s: %d tags found, clean desc: %q", tc.name, len(tags), cleanDesc)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d5dea75 and a905707.

📒 Files selected for processing (3)
  • main.go (4 hunks)
  • main_test.go (1 hunks)
  • tag_sample_test.go (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Use standard formatting (gofmt) and idiomatic Go style
Favor small, testable functions in Go
Keep exported Go APIs documented with Go-style comments
Maintain ≥80% coverage for non-data packages and ≥90% for data packages when adding new testable Go code

Files:

  • main.go
  • main_test.go
  • tag_sample_test.go
{**/*.go,.github/scripts/**/*.js}

📄 CodeRabbit inference engine (AGENTS.md)

Use American English spelling in code comments

Files:

  • main.go
  • main_test.go
  • tag_sample_test.go
🪛 GitHub Actions: tests
main_test.go

[error] 129-129: expected 'go-githubauth' but actual is 'go-guardian'


[error] 129-129: expected 'go-guardian' but actual is 'go-githubauth'


[error] 133-133: expected order is: authboss, branca, casbin, cookiestxt, go-githubauth, go-guardian, go-iam, go-jose, go-jwt, gtool, jwx, keto, loginsrv, oauth2, oidc, openfga, osin, otpgen, otpgo, paseto, permissions, scope, scs, securecookie, session, sessions, sessionup, sjwt, spicedb, x509proxy


[error] 448-448: Expected to pass but found invalid tag in: project-name [lib] [active] Description without separator [.go] [error] (reason: Without ' - ' separator, entire text is tag zone, but non-letters ignored)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (2)
main_test.go (2)

50-61: Note on TestAlpha failures (ordering).

The reported “expected order” diffs are content issues in README, not test/code changes. Please re-sort the affected list items in README to satisfy TestAlpha.


364-454: Align edge-case validation with leading-token rule (fixes CI failure).

When no hyphen is present, only validate an initial run of bracketed tags; ignore later brackets. This makes “No tag separator” case pass (it has [error] later).

Apply this diff:

-      // Split description at first " - " to get tag zone
-      parts := strings.SplitN(tc.description, " - ", 2)
-      tagZone := parts[0]
-
-      // Check for bracketed tokens in tag zone only
-      tagPattern := regexp.MustCompile(`\[([^\]]+)\]`)
-      matches := tagPattern.FindAllStringSubmatch(tagZone, -1)
-
-      for _, match := range matches {
-        token := match[1]
-        
-        // Only validate letters-only tokens
-        lettersOnly := regexp.MustCompile(`^[A-Za-z]+$`)
-        if !lettersOnly.MatchString(token) {
-          continue // Skip non-letters-only tokens
-        }
-
-        // Check if it's a valid tag
-        if !validTypeTags[token] && !validStatusTags[token] {
-          hasInvalidTag = true
-          break
-        }
-      }
+      // Split description at first " - " to get tag zone and scan only leading tags
+      parts := strings.SplitN(tc.description, " - ", 2)
+      tagZone := parts[0]
+      reTagAtStart := regexp.MustCompile(`^\s*\[([A-Za-z]+)\]\s*`)
+      zone := tagZone
+      for {
+        m := reTagAtStart.FindStringSubmatchIndex(zone)
+        if m == nil {
+          break
+        }
+        token := zone[m[2]:m[3]]
+        if !validTypeTags[token] && !validStatusTags[token] {
+          hasInvalidTag = true
+          break
+        }
+        zone = zone[m[1]:]
+      }

Likely an incorrect or invalid review comment.

 Add optional [lib]/[app] type tags for project categorization
 Add optional [active]/[stalled]/[unmaintained] status tags
 Implement tag parsing and validation logic in main.go
 Add color-coded CSS styling for visual tag distinction in tmpl/assets/awesome-go.css
 Update HTML templates to display tag badges with tooltips
 Add comprehensive test suite for tag functionality
 Update CONTRIBUTING.md with tagging guidelines and examples
 Maintain full backwards compatibility with existing entries
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (1)
main_test.go (1)

142-170: Validate only leading, contiguous bracketed tokens in the tag zone.

Prevents false positives when there’s no separator or when brackets appear later for versions/file types. Mirrors how tags are written.

- doc.Find("body li > a:first-child").Each(func(_ int, s *goquery.Selection) {
-     parent := s.Parent()
-     description := parent.Text()
-
-     // Split description at first " - " to get tag zone
-     parts := strings.SplitN(description, " - ", 2)
-     tagZone := parts[0]
-
-     // Check for bracketed tokens in tag zone only
-     tagPattern := regexp.MustCompile(`\[([^\]]+)\]`)
-     matches := tagPattern.FindAllStringSubmatch(tagZone, -1)
-
-     for _, match := range matches {
-         token := match[1]
-         
-         // Only validate letters-only tokens (ignore things like file extensions, type signatures)
-         lettersOnly := regexp.MustCompile(`^[A-Za-z]+$`)
-         if !lettersOnly.MatchString(token) {
-             continue // Skip non-letters-only tokens
-         }
-
-         // Check if it's a valid tag
-         if !validTypeTags[token] && !validStatusTags[token] {
-             t.Errorf("Invalid tag [%s] found in tag zone of: %s", token, description)
-         }
-     }
- })
+ doc.Find("body li").Each(func(_ int, li *goquery.Selection) {
+     a := li.Find("a:first-child")
+     title := a.Text()
+     full := strings.TrimSpace(li.Text())
+     rest := strings.TrimSpace(strings.TrimPrefix(full, title))
+     pre, _, _ := strings.Cut(rest, " - ")
+
+     reTagAtStart := regexp.MustCompile(`^\s*\[([A-Za-z]+)\]\s*`)
+     zone := pre
+     for {
+         m := reTagAtStart.FindStringSubmatchIndex(zone)
+         if m == nil {
+             break
+         }
+         token := zone[m[2]:m[3]]
+         if !validTypeTags[token] && !validStatusTags[token] {
+             t.Errorf("Invalid tag [%s] found in tag zone of: %s", token, li.Text())
+             break
+         }
+         zone = zone[m[1]:]
+     }
+ })
🧹 Nitpick comments (3)
package.json (1)

10-10: Consider committing a package-lock.json for reproducibility.

Using a caret version constraint (^1.10.1) allows minor and patch version updates. While this is generally acceptable, you should commit package-lock.json (or yarn.lock if using yarn) to ensure reproducible builds across environments and CI/CD runs.

Run npm install locally and commit the generated package-lock.json to the repository to lock exact dependency versions.

main_test.go (2)

318-336: Make tag value checks order‑insensitive to avoid brittle tests.

If parsing order changes (e.g., normalization), tests shouldn’t fail.

-            // Check actual tag values
-            for i, expectedTag := range tc.expectedTags {
-                if i >= len(tags) {
-                    t.Errorf("Missing tag at index %d", i)
-                    continue
-                }
-                
-                actualTag := tags[i]
-                if actualTag.Type != expectedTag.tagType || actualTag.Status != expectedTag.status {
-                    t.Errorf("Tag mismatch at index %d. Expected {Type: %q, Status: %q}, got {Type: %q, Status: %q}",
-                        i, expectedTag.tagType, expectedTag.status, actualTag.Type, actualTag.Status)
-                }
-            }
+            // Order-insensitive comparison
+            toPairs := func(ts []Tag) []string {
+                out := make([]string, 0, len(ts))
+                for _, t := range ts {
+                    out = append(out, t.Type+"|"+t.Status)
+                }
+                sort.Strings(out)
+                return out
+            }
+            expPairs := make([]string, 0, len(tc.expectedTags))
+            for _, e := range tc.expectedTags {
+                expPairs = append(expPairs, e.tagType+"|"+e.status)
+            }
+            sort.Strings(expPairs)
+            actPairs := toPairs(tags)
+            if strings.Join(expPairs, ",") != strings.Join(actPairs, ",") {
+                t.Errorf("Expected tags %v, got %v", expPairs, actPairs)
+            }

427-446: Precompile regexes once per test for performance/readability.

Avoid recompiling inside loops.

-            // Check for bracketed tokens in tag zone only
-            tagPattern := regexp.MustCompile(`\[([^\]]+)\]`)
+            // Check for bracketed tokens in tag zone only
+            tagPattern := regexp.MustCompile(`\[([^\]]+)\]`)
+            lettersOnly := regexp.MustCompile(`^[A-Za-z]+$`)
             matches := tagPattern.FindAllStringSubmatch(tagZone, -1)
 
             for _, match := range matches {
                 token := match[1]
-                
-                // Only validate letters-only tokens
-                lettersOnly := regexp.MustCompile(`^[A-Za-z]+$`)
                 if !lettersOnly.MatchString(token) {
                     continue // Skip non-letters-only tokens
                 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a905707 and 1d2d800.

📒 Files selected for processing (2)
  • main_test.go (1 hunks)
  • package.json (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Use standard formatting (gofmt) and idiomatic Go style
Favor small, testable functions in Go
Keep exported Go APIs documented with Go-style comments
Maintain ≥80% coverage for non-data packages and ≥90% for data packages when adding new testable Go code

Files:

  • main_test.go
{**/*.go,.github/scripts/**/*.js}

📄 CodeRabbit inference engine (AGENTS.md)

Use American English spelling in code comments

Files:

  • main_test.go
🪛 GitHub Actions: tests
main_test.go

[error] 400-400: duplicate field name reason in struct literal.

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (3)
package.json (1)

1-19: Verification complete: the referenced script exists and is properly integrated.

The .github/scripts/check-quality.js file exists and implements quality checks for Go repositories, validating repository accessibility, go.mod presence, SemVer releases, Go Report Card grades, coverage links, and pkg.go.dev availability—confirming this Node.js addition is legitimate GitHub Actions automation for the Go project's PR validation workflow.

The only minor issue remaining is the placeholder test script at line 7 (exits unconditionally with error code 1). Consider implementing a basic test or removing the test script if not needed.

main_test.go (2)

172-241: Good coverage for parsing and normalization.

Cases exercise tags in-line, punctuation spacing, and pre-hyphen placement. Looks solid.


456-518: Cleanup rules look comprehensive.

Covers collapsing spaces, punctuation spacing, leading hyphen trimming, and preservation of mid-string hyphens.

"description": "Quality check scripts for awesome-go repository",
"main": ".github/scripts/check-quality.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Replace placeholder test script with implementation or remove it.

The test script at line 7 is a placeholder that unconditionally exits with error code 1, which will cause CI/CD pipelines to fail when running npm test.

Either implement the test script or remove it entirely if not yet needed:

  "scripts": {
-   "test": "echo \"Error: no test specified\" && exit 1"
+   "test": "node .github/scripts/check-quality.js"
  },

Or, if tests are not yet ready:

  "scripts": {
-   "test": "echo \"Error: no test specified\" && exit 1"
  },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"test": "echo \"Error: no test specified\" && exit 1"
"scripts": {
},
🤖 Prompt for AI Agents
In package.json around line 7, the "test" script is a failing placeholder that
exits with code 1; replace it with a real test command or remove/neutralize it
so CI won't fail. If you have a test runner, set "test" to the appropriate
command (e.g., run your test script or jest/mocha command); if tests aren't
ready, remove the "test" entry or set it to a no-op (e.g., a command that exits
0 or prints a message) to avoid failing CI. Ensure package.json remains valid
JSON and run npm test locally after the change to confirm the script behaves as
intended.

- Add debug output step to show quality check results in workflow logs
- Enhance quality script with detailed console logging for each check
- Add comprehensive error handling with stack traces in catch blocks
- Implement dual output strategy (@actions/core + GITHUB_OUTPUT fallback)
- Include final results summary logging for easier troubleshooting

This resolves workflow failure visibility issues where critical check
failures weren't showing details in the job logs.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1d2d800 and e2766c0.

📒 Files selected for processing (2)
  • .github/scripts/check-quality.js (4 hunks)
  • .github/workflows/pr-quality-check.yaml (2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
.github/scripts/**/*.js

📄 CodeRabbit inference engine (AGENTS.md)

.github/scripts/**/*.js: JavaScript (GitHub Action scripts) must remain compatible with Node 20
Uphold strict mode and existing patterns in Action scripts (async helpers, early returns, descriptive errors)

Files:

  • .github/scripts/check-quality.js
{**/*.go,.github/scripts/**/*.js}

📄 CodeRabbit inference engine (AGENTS.md)

Use American English spelling in code comments

Files:

  • .github/scripts/check-quality.js
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Codacy Static Code Analysis
🔇 Additional comments (6)
.github/scripts/check-quality.js (4)

17-17: LGTM!

The import of @actions/core is correctly added to support the enhanced output mechanism.


241-257: Enhanced output mechanism with proper fallback.

The dual approach (core.setOutput + GITHUB_OUTPUT fallback) ensures compatibility across different runner versions. The try-catch blocks prevent crashes while warning on failure.


284-349: Excellent debugging enhancements.

The comprehensive logging for each check with emoji indicators and clear pass/fail messages significantly improves observability. The distinction between missing optional coverage (⚠️) and failed checks (❌) is particularly helpful.


365-370: LGTM!

The final results summary provides a clear overview of all check outcomes, making it easy to understand the overall status at a glance.

.github/workflows/pr-quality-check.yaml (2)

27-35: LGTM!

The debug step is well-designed with if: always() ensuring it runs regardless of check outcome, and properly formatted output references make troubleshooting straightforward.


51-51: LGTM!

The additional message helpfully directs users to the debug output above, improving the developer experience when checks fail.

Comment on lines 377 to 404
main().catch((e) => {
console.error('💥 QUALITY CHECK SCRIPT CRASHED:', e.message);
console.error('📄 Stack trace:', e.stack);

const crashComment = `## 💥 Quality Check Error
The quality check script encountered an error:
**Error:** ${e.message}
**Stack trace:**
\`\`\`
${e.stack}
\`\`\`
Please review the script or contact maintainers.`;

const msg = `Quality checks failed to run: ${e?.message || e}`;
console.log('🔍 QUALITY CHECK FAILED - Reason: Script crashed with error');
console.log('📝 Error details written to outputs for workflow');

if (GITHUB_OUTPUT) {
fs.appendFileSync(GITHUB_OUTPUT, `comment<<EOF\n${msg}\nEOF\n`);
fs.appendFileSync(GITHUB_OUTPUT, `comment<<EOF\n${crashComment}\nEOF\n`);
fs.appendFileSync(GITHUB_OUTPUT, `fail<<EOF\ntrue\nEOF\n`);
fs.appendFileSync(GITHUB_OUTPUT, `labels<<EOF\n["quality-check-error"]\nEOF\n`);
}
process.exitCode = 0; // Do not crash the job here; let the fail step handle it
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Inconsistent output handling in crash path.

The crash handler directly writes to GITHUB_OUTPUT (lines 399-401) instead of using the setOutput() function, bypassing the dual-mechanism approach (core.setOutput + fallback) established earlier in the file.

Apply this diff to maintain consistency:

-  if (GITHUB_OUTPUT) {
-    fs.appendFileSync(GITHUB_OUTPUT, `comment<<EOF\n${crashComment}\nEOF\n`);
-    fs.appendFileSync(GITHUB_OUTPUT, `fail<<EOF\ntrue\nEOF\n`);
-    fs.appendFileSync(GITHUB_OUTPUT, `labels<<EOF\n["quality-check-error"]\nEOF\n`);
-  }
+  setOutput('comment', crashComment);
+  setOutput('fail', 'true');
+  setOutput('labels', '["quality-check-error"]');
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
main().catch((e) => {
console.error('💥 QUALITY CHECK SCRIPT CRASHED:', e.message);
console.error('📄 Stack trace:', e.stack);
const crashComment = `## 💥 Quality Check Error
The quality check script encountered an error:
**Error:** ${e.message}
**Stack trace:**
\`\`\`
${e.stack}
\`\`\`
Please review the script or contact maintainers.`;
const msg = `Quality checks failed to run: ${e?.message || e}`;
console.log('🔍 QUALITY CHECK FAILED - Reason: Script crashed with error');
console.log('📝 Error details written to outputs for workflow');
if (GITHUB_OUTPUT) {
fs.appendFileSync(GITHUB_OUTPUT, `comment<<EOF\n${msg}\nEOF\n`);
fs.appendFileSync(GITHUB_OUTPUT, `comment<<EOF\n${crashComment}\nEOF\n`);
fs.appendFileSync(GITHUB_OUTPUT, `fail<<EOF\ntrue\nEOF\n`);
fs.appendFileSync(GITHUB_OUTPUT, `labels<<EOF\n["quality-check-error"]\nEOF\n`);
}
process.exitCode = 0; // Do not crash the job here; let the fail step handle it
});
main().catch((e) => {
console.error('💥 QUALITY CHECK SCRIPT CRASHED:', e.message);
console.error('📄 Stack trace:', e.stack);
const crashComment = `## 💥 Quality Check Error
The quality check script encountered an error:
**Error:** ${e.message}
**Stack trace:**
\`\`\`
${e.stack}
\`\`\`
Please review the script or contact maintainers.`;
const msg = `Quality checks failed to run: ${e?.message || e}`;
console.log('🔍 QUALITY CHECK FAILED - Reason: Script crashed with error');
console.log('📝 Error details written to outputs for workflow');
setOutput('comment', crashComment);
setOutput('fail', 'true');
setOutput('labels', '["quality-check-error"]');
process.exitCode = 0; // Do not crash the job here; let the fail step handle it
});
🤖 Prompt for AI Agents
.github/scripts/check-quality.js around lines 377 to 404: the crash handler
writes directly to GITHUB_OUTPUT via fs.appendFileSync which bypasses the
file/core dual-output helper used elsewhere; replace those direct writes with
calls to the existing setOutput(name, value) helper for "comment", "fail", and
"labels" (use the crashComment string, "true", and '["quality-check-error"]'
respectively) so the same core.setOutput + fallback behavior is used; keep the
surrounding logging and process.exitCode = 0 intact.

- Fixed duplicate 'reason' field in TestTagValidationEdgeCases struct literal
- Restored proper test case structure with description field
- Corrected shouldPass value for 'Type signatures' test case

Resolves: ./main_test.go:400:4: duplicate field name reason in struct literal
- pr-quality-helper.ps1: Provides step-by-step guidance for resolving PR quality check failures
- pr-template-generator.ps1: Generates properly formatted PR bodies with all required quality check links

These tools help contributors understand and resolve quality check requirements more easily.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
pr-template-generator.ps1 (2)

15-40: Consider URL encoding for defense-in-depth.

While the validation patterns should prevent most issues, adding URL encoding provides an extra safety layer for edge cases like hyphens or dots in repository names.

You could add a helper to URL-encode the path components:

function Generate-PRTemplate {
    param(
        # ... parameters ...
    )
    
    # URL-encode repository path components
    $encodedOwner = [System.Uri]::EscapeDataString($RepoOwner)
    $encodedRepo = [System.Uri]::EscapeDataString($RepoName)
    
    $template = @"
## Description
Add [$RepoName] - $PackageDescription

## Quality Check Links
forge link: https://github.com/$encodedOwner/$encodedRepo
pkg.go.dev: https://pkg.go.dev/github.com/$encodedOwner/$encodedRepo
goreportcard.com: https://goreportcard.com/report/github.com/$encodedOwner/$encodedRepo
"@
    # ... rest of function
}

42-48: Consider adding PowerShell comment-based help.

The current Write-Host example is helpful, but PowerShell's standard approach is comment-based help, which integrates with Get-Help and provides better discoverability.

You could add this before the function:

<#
.SYNOPSIS
    Generates a PR template for awesome-go package submissions.

.DESCRIPTION
    Creates a formatted PR template with quality check links and package information.

.PARAMETER RepoOwner
    The GitHub repository owner/organization name.

.PARAMETER RepoName
    The GitHub repository name.

.PARAMETER PackageDescription
    Brief description of what the package does.

.PARAMETER CoverageService
    Coverage service to use. Valid values: "coveralls" (default), "codecov".

.EXAMPLE
    Generate-PRTemplate -RepoOwner "username" -RepoName "package-name" -PackageDescription "Brief description"
    
.EXAMPLE
    Generate-PRTemplate -RepoOwner "golang" -RepoName "example" -PackageDescription "Example package" -CoverageService "codecov"
#>
function Generate-PRTemplate {
    # ... function body ...
}

This enables Get-Help Generate-PRTemplate for integrated documentation.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 50250c9 and 883ca35.

📒 Files selected for processing (2)
  • pr-quality-helper.ps1 (1 hunks)
  • pr-template-generator.ps1 (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • pr-quality-helper.ps1
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Codacy Static Code Analysis

- Remove UTF-8 BOM to prevent script execution failures on Linux/macOS
- Add comprehensive parameter validation:
  * RepoOwner: ValidatePattern for valid GitHub usernames
  * RepoName: ValidatePattern for valid repository names
  * PackageDescription: ValidateNotNullOrEmpty
  * CoverageService: ValidateSet for 'coveralls' or 'codecov' only
- Improve error handling with descriptive validation messages
- Enhance script robustness across different PowerShell environments
…ove logging

A — Make goreportcard non-critical (treat as warning):
- Changed missing goreportcard from FAIL to 'missing (non-critical)'
- Changed low/unreachable grades from FAIL to WARN
- Removed criticalFail = true for goreportcard issues
- PRs no longer fail due to missing or low-grade goreportcard

B — Improve script logging and ensure outputs are set:
- Added concise CI-friendly summary to stdout after each run
- Enhanced top-level error handler with better logging
- Ensures GitHub Actions outputs are visible in job logs
- Improved debugging experience for workflow failures

C — Make the workflow fail step more informative:
- Updated final fail step to reference debug output location
- Points users to 'pr-quality-check' sticky comment for full details
- Provides clear guidance on where to find failure information

These improvements maintain code quality standards while making goreportcard
optional and significantly improving the debugging experience for contributors.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant