Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Architecture Diagrams #34

Merged
merged 1 commit into from
Dec 18, 2024
Merged

Add Architecture Diagrams #34

merged 1 commit into from
Dec 18, 2024

Conversation

nao1215
Copy link
Owner

@nao1215 nao1215 commented Dec 18, 2024

Summary by CodeRabbit

  • New Features

    • Added a new section for "Architecture Diagrams" in the README, including code examples and visual representations.
    • Introduced functionality for creating architecture diagrams using Mermaid syntax, including services, junctions, and groups.
    • Added predefined icon types for use in architecture diagrams.
  • Bug Fixes

    • Minor formatting adjustments made throughout the documentation.
  • Tests

    • Comprehensive unit tests added for architecture diagram functionality, including groups and junctions.
  • Documentation

    • Enhanced README and generated documentation with clearer examples and expanded feature descriptions.

Copy link

coderabbitai bot commented Dec 18, 2024

Walkthrough

The pull request introduces a comprehensive beta feature for generating architecture diagrams using Mermaid syntax. A new arch package is created within the Mermaid library, providing a fluent interface to build complex architecture diagrams. The implementation includes support for services, junctions, groups, and edges, with a flexible configuration system. The changes span multiple files, adding new types, methods, and tests to support the architecture diagram generation functionality.

Changes

File Change Summary
README.md Added new section "Architecture Diagrams (beta feature)" with Mermaid diagram example
doc/architecture/generated.md New file with architecture diagram section
doc/architecture/main.go New program to generate Mermaid architecture diagram
mermaid/arch/architecture.go Core Architecture struct and methods for diagram building
mermaid/arch/config.go Configuration setup for architecture diagrams
mermaid/arch/edge.go Added edge representation and methods
mermaid/arch/group.go Methods for creating groups in architecture diagrams
mermaid/arch/icon.go Defined icons for architecture components
mermaid/arch/junction.go Methods for adding junctions to diagrams
mermaid/arch/service.go Methods for adding services to architecture diagrams

Sequence Diagram

sequenceDiagram
    participant A as Architecture Builder
    participant S as Service
    participant G as Group
    participant J as Junction
    participant E as Edge

    A->>S: Add Service
    A->>G: Create Group
    A->>J: Add Junction
    A->>E: Define Edges
    A-->>A: Build Diagram
Loading

Poem

🐰 Architect Rabbit's Diagram Dance

With Mermaid's magic, lines take flight,
Services, junctions, groups so bright!
Edges connect, icons gleam,
A blueprint drawn from a coder's dream.
Architecture flows, clean and neat! 🏗️

Tip

CodeRabbit's docstrings feature is now available as part of our Early Access Program! Simply use the command @coderabbitai generate docstrings to have CodeRabbit automatically generate docstrings for your pull request. We would love to hear your feedback on Discord.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

Code Metrics Report

Coverage Test Execution Time
92.6% 13s

Code coverage of files in pull request scope (87.0%)

Files Coverage
mermaid/arch/architecture.go 69.2%
mermaid/arch/config.go 100.0%
mermaid/arch/edge.go 100.0%
mermaid/arch/group.go 100.0%
mermaid/arch/junction.go 100.0%
mermaid/arch/service.go 100.0%
mermaid/er/config.go 100.0%

Reported by octocov

Copy link

@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: 6

🧹 Nitpick comments (19)
mermaid/arch/icon.go (4)

3-6: Consider enhancing the documentation with usage examples.

The current documentation could be more comprehensive by including:

  • Example usage in architecture diagrams
  • Whether custom icons are supported
  • Format requirements for custom icons (if supported)

5-5: Provide more context for the AWS icons TODO.

The TODO comment would be more actionable with additional details about:

  • Which AWS icons are planned
  • Any specific requirements or constraints
  • Implementation timeline

Would you like me to help create a GitHub issue to track the AWS icons implementation with detailed requirements?


6-6: Consider using a more type-safe approach.

The current string-based implementation allows for any string value. Consider using an enumeration pattern or validation to ensure only valid icons are used.

Example approach:

type Icon string

func (i Icon) Validate() error {
    valid := map[Icon]bool{
        IconCloud:    true,
        IconDatabase: true,
        IconDisk:     true,
        IconInternet: true,
        IconServer:   true,
    }
    if !valid[i] {
        return fmt.Errorf("invalid icon: %s", i)
    }
    return nil
}

8-19: Consider grouping related icons.

The current implementation lists icons sequentially. Consider grouping related icons (e.g., storage-related, network-related) using comments or separate constant blocks for better organization as the icon set grows.

Example organization:

const (
    // Network-related icons
    IconCloud    Icon = "cloud"
    IconInternet Icon = "internet"

    // Storage-related icons
    IconDatabase Icon = "database"
    IconDisk     Icon = "disk"

    // Compute-related icons
    IconServer   Icon = "server"
)
mermaid/arch/config.go (2)

3-4: Document intended configuration options

The empty config struct suggests this is a work in progress. Consider documenting the planned configuration options in the struct's documentation to help other developers understand the intended usage and future direction.


11-12: Add example usage for Option type

The Option type implements the functional options pattern, but lacks usage examples. Consider adding example configurations to help other developers understand how to use this pattern correctly.

Example addition:

// Option sets the options for the Architecture struct.
// Example usage:
//
//	arch.NewArchitecture(
//		arch.WithTheme("default"),
//		arch.WithDirection("TB"),
//	)
type Option func(*config)
mermaid/arch/junction.go (3)

5-7: Enhance documentation with visual examples

While the syntax documentation is helpful, consider adding a visual example of how junctions appear in the generated diagram. This would help developers understand the visual impact of their code.

Example addition:

// Junction are a special type of node which acts as a potential 4-way split between edges.
// Syntax: junction {junction id} (in {parent id})?
//
// Example:
//   a.Junction("j1")
//
// Results in:
//   [Service A] --> j1
//   j1 --> [Service B]
//   j1 --> [Service C]

12-17: Fix method naming inconsistency

The method name JunctionsInParent (plural) is inconsistent with the singular Junction. Since it creates a single junction, consider renaming to JunctionInParent for consistency.

-func (a *Architecture) JunctionsInParent(junctionID, parentGroupID string) *Architecture {
+func (a *Architecture) JunctionInParent(junctionID, parentGroupID string) *Architecture {

1-1: Consider architectural improvements for robustness

Several architectural improvements could enhance the implementation:

  1. Create a dedicated validation package for common identifier and input checks
  2. Implement a MermaidBuilder type for efficient string construction
  3. Add a consistent error handling strategy across all methods
  4. Consider using an interface for the Architecture type to allow different implementations

This would improve maintainability and make the codebase more robust.

mermaid/arch/group.go (1)

12-17: Consider adding validation for empty parameters.

While the implementation is good, consider adding validation for empty parameters to prevent potential issues with malformed diagram syntax.

 func (a *Architecture) GroupInParentGroup(groupID string, icon Icon, title, parentGroupID string) *Architecture {
+    if groupID == "" || parentGroupID == "" {
+        return a
+    }
     a.body = append(a.body, fmt.Sprintf("    group %s(%s)[%s] in %s", groupID, icon, title, parentGroupID))
     return a
 }
mermaid/arch/junction_test.go (1)

11-33: Consider adding more test cases for edge scenarios.

The test implementation is solid with good practices:

  • Parallel test execution
  • Proper error handling
  • Line ending normalization
  • Detailed diff comparison

Consider adding test cases for:

  • Empty junction ID or parent group
  • Special characters in IDs
  • Multiple junctions in the same parent
mermaid/arch/group_test.go (1)

11-33: Enhance test coverage with additional scenarios.

While the basic test case is good, consider adding tests for:

  • Empty group ID, title, or parent group
  • Special characters in group ID or title
  • Nested groups (multiple levels)
  • Groups with various icon types
mermaid/arch/architecture.go (2)

46-55: Simplify error handling in Build() method

The error handling in Build() can be simplified by removing the nested if condition.

 func (a *Architecture) Build() error {
 	if _, err := a.dest.Write([]byte(a.String())); err != nil {
-		if a.err != nil {
-			return fmt.Errorf("failed to write: %w: %s", err, a.err.Error()) //nolint:wrapcheck
-		}
-		return fmt.Errorf("failed to write: %w", err)
+		var errMsg string
+		if a.err != nil {
+			errMsg = fmt.Sprintf(": %s", a.err.Error())
+		}
+		return fmt.Errorf("failed to write%s: %w", errMsg, err)
 	}
 	return nil
 }

41-44: Consider using strings.Builder for better performance

The String() method could be more efficient by using strings.Builder instead of strings.Join.

 func (a *Architecture) String() string {
-	return strings.Join(a.body, internal.LineFeed())
+	var builder strings.Builder
+	for i, line := range a.body {
+		if i > 0 {
+			builder.WriteString(internal.LineFeed())
+		}
+		builder.WriteString(line)
+	}
+	return builder.String()
 }
mermaid/arch/edge.go (1)

32-42: Enhance Edge struct documentation

The Edge struct documentation could be more detailed about field requirements and valid values.

-// Edge represents an edge between two services.
-// The edge can be customized with the Position and Arrow.
+// Edge represents a connection between two services or junctions in an architecture diagram.
+// The edge is defined by:
+// - ServiceID: Required. The identifier of the service or junction
+// - Position: Required. The connection point (Top, Bottom, Left, Right)
+// - Arrow: Optional. The arrow direction at this end of the connection
 type Edge struct {
doc/architecture/main.go (1)

23-97: Improve readability of diagram construction

  1. The long chain of method calls could be split for better readability
  2. The use of io.Discard needs explanation
+// createServices adds all services to the architecture
+func createServices(a *arch.Architecture) *arch.Architecture {
+	return a.
+		Service("left_disk", arch.IconDisk, "Disk").
+		Service("top_disk", arch.IconDisk, "Disk").
+		Service("bottom_disk", arch.IconDisk, "Disk").
+		Service("top_gateway", arch.IconInternet, "Gateway").
+		Service("bottom_gateway", arch.IconInternet, "Gateway")
+}
+
+// createJunctions adds all junctions to the architecture
+func createJunctions(a *arch.Architecture) *arch.Architecture {
+	return a.
+		Junction("junctionCenter").
+		Junction("junctionRight")
+}
+
+// createEdges adds all connections between services and junctions
+func createEdges(a *arch.Architecture) *arch.Architecture {
+	// Add edges here...
+}
+
 func main() {
 	// ...
-	diagram := arch.NewArchitecture(io.Discard).
-		Service("left_disk", arch.IconDisk, "Disk").
-		// ... long chain of methods
+	// Using io.Discard as we only need the string representation
+	a := arch.NewArchitecture(io.Discard)
+	diagram := createServices(a)
+	diagram = createJunctions(diagram)
+	diagram = createEdges(diagram)
+	diagramStr := diagram.String()
mermaid/arch/architecture_test.go (2)

96-102: Consider enhancing error messages.

The error messages could be more descriptive to help identify issues faster.

-			t.Errorf("unexpected error: %v", err)
+			t.Errorf("failed to build architecture diagram: %v", err)

17-126: Consider adding negative test cases.

The test covers the happy path well, but consider adding test cases for error scenarios:

  • Invalid service IDs
  • Duplicate junctions
  • Invalid edge connections

Would you like me to help generate these additional test cases?

README.md (1)

789-789: Add language specification to fenced code block.

The fenced code block should specify the language for proper syntax highlighting.

-````
+````markdown
🧰 Tools
🪛 Markdownlint (0.37.0)

789-789: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 25fbbce and 791d32e.

⛔ Files ignored due to path filters (1)
  • doc/architecture/image.png is excluded by !**/*.png
📒 Files selected for processing (14)
  • README.md (1 hunks)
  • doc/architecture/generated.md (1 hunks)
  • doc/architecture/main.go (1 hunks)
  • mermaid/arch/architecture.go (1 hunks)
  • mermaid/arch/architecture_test.go (1 hunks)
  • mermaid/arch/config.go (1 hunks)
  • mermaid/arch/edge.go (1 hunks)
  • mermaid/arch/group.go (1 hunks)
  • mermaid/arch/group_test.go (1 hunks)
  • mermaid/arch/icon.go (1 hunks)
  • mermaid/arch/junction.go (1 hunks)
  • mermaid/arch/junction_test.go (1 hunks)
  • mermaid/arch/service.go (1 hunks)
  • mermaid/er/config.go (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • mermaid/er/config.go
  • doc/architecture/generated.md
🧰 Additional context used
🪛 Markdownlint (0.37.0)
README.md

686-686: Column: 1
Hard tabs

(MD010, no-hard-tabs)


687-687: Column: 1
Hard tabs

(MD010, no-hard-tabs)


689-689: Column: 1
Hard tabs

(MD010, no-hard-tabs)


690-690: Column: 1
Hard tabs

(MD010, no-hard-tabs)


696-696: Column: 1
Hard tabs

(MD010, no-hard-tabs)


697-697: Column: 1
Hard tabs

(MD010, no-hard-tabs)


698-698: Column: 1
Hard tabs

(MD010, no-hard-tabs)


699-699: Column: 1
Hard tabs

(MD010, no-hard-tabs)


700-700: Column: 1
Hard tabs

(MD010, no-hard-tabs)


702-702: Column: 1
Hard tabs

(MD010, no-hard-tabs)


703-703: Column: 1
Hard tabs

(MD010, no-hard-tabs)


704-704: Column: 1
Hard tabs

(MD010, no-hard-tabs)


705-705: Column: 1
Hard tabs

(MD010, no-hard-tabs)


706-706: Column: 1
Hard tabs

(MD010, no-hard-tabs)


707-707: Column: 1
Hard tabs

(MD010, no-hard-tabs)


708-708: Column: 1
Hard tabs

(MD010, no-hard-tabs)


709-709: Column: 1
Hard tabs

(MD010, no-hard-tabs)


710-710: Column: 1
Hard tabs

(MD010, no-hard-tabs)


711-711: Column: 1
Hard tabs

(MD010, no-hard-tabs)


712-712: Column: 1
Hard tabs

(MD010, no-hard-tabs)


713-713: Column: 1
Hard tabs

(MD010, no-hard-tabs)


714-714: Column: 1
Hard tabs

(MD010, no-hard-tabs)


715-715: Column: 1
Hard tabs

(MD010, no-hard-tabs)


716-716: Column: 1
Hard tabs

(MD010, no-hard-tabs)


717-717: Column: 1
Hard tabs

(MD010, no-hard-tabs)


718-718: Column: 1
Hard tabs

(MD010, no-hard-tabs)


719-719: Column: 1
Hard tabs

(MD010, no-hard-tabs)


720-720: Column: 1
Hard tabs

(MD010, no-hard-tabs)


721-721: Column: 1
Hard tabs

(MD010, no-hard-tabs)


722-722: Column: 1
Hard tabs

(MD010, no-hard-tabs)


723-723: Column: 1
Hard tabs

(MD010, no-hard-tabs)


724-724: Column: 1
Hard tabs

(MD010, no-hard-tabs)


725-725: Column: 1
Hard tabs

(MD010, no-hard-tabs)


726-726: Column: 1
Hard tabs

(MD010, no-hard-tabs)


727-727: Column: 1
Hard tabs

(MD010, no-hard-tabs)


728-728: Column: 1
Hard tabs

(MD010, no-hard-tabs)


729-729: Column: 1
Hard tabs

(MD010, no-hard-tabs)


730-730: Column: 1
Hard tabs

(MD010, no-hard-tabs)


731-731: Column: 1
Hard tabs

(MD010, no-hard-tabs)


732-732: Column: 1
Hard tabs

(MD010, no-hard-tabs)


733-733: Column: 1
Hard tabs

(MD010, no-hard-tabs)


734-734: Column: 1
Hard tabs

(MD010, no-hard-tabs)


735-735: Column: 1
Hard tabs

(MD010, no-hard-tabs)


736-736: Column: 1
Hard tabs

(MD010, no-hard-tabs)


737-737: Column: 1
Hard tabs

(MD010, no-hard-tabs)


738-738: Column: 1
Hard tabs

(MD010, no-hard-tabs)


739-739: Column: 1
Hard tabs

(MD010, no-hard-tabs)


740-740: Column: 1
Hard tabs

(MD010, no-hard-tabs)


741-741: Column: 1
Hard tabs

(MD010, no-hard-tabs)


742-742: Column: 1
Hard tabs

(MD010, no-hard-tabs)


743-743: Column: 1
Hard tabs

(MD010, no-hard-tabs)


744-744: Column: 1
Hard tabs

(MD010, no-hard-tabs)


745-745: Column: 1
Hard tabs

(MD010, no-hard-tabs)


746-746: Column: 1
Hard tabs

(MD010, no-hard-tabs)


747-747: Column: 1
Hard tabs

(MD010, no-hard-tabs)


748-748: Column: 1
Hard tabs

(MD010, no-hard-tabs)


749-749: Column: 1
Hard tabs

(MD010, no-hard-tabs)


750-750: Column: 1
Hard tabs

(MD010, no-hard-tabs)


751-751: Column: 1
Hard tabs

(MD010, no-hard-tabs)


752-752: Column: 1
Hard tabs

(MD010, no-hard-tabs)


753-753: Column: 1
Hard tabs

(MD010, no-hard-tabs)


754-754: Column: 1
Hard tabs

(MD010, no-hard-tabs)


755-755: Column: 1
Hard tabs

(MD010, no-hard-tabs)


756-756: Column: 1
Hard tabs

(MD010, no-hard-tabs)


757-757: Column: 1
Hard tabs

(MD010, no-hard-tabs)


758-758: Column: 1
Hard tabs

(MD010, no-hard-tabs)


759-759: Column: 1
Hard tabs

(MD010, no-hard-tabs)


760-760: Column: 1
Hard tabs

(MD010, no-hard-tabs)


761-761: Column: 1
Hard tabs

(MD010, no-hard-tabs)


762-762: Column: 1
Hard tabs

(MD010, no-hard-tabs)


763-763: Column: 1
Hard tabs

(MD010, no-hard-tabs)


764-764: Column: 1
Hard tabs

(MD010, no-hard-tabs)


765-765: Column: 1
Hard tabs

(MD010, no-hard-tabs)


766-766: Column: 1
Hard tabs

(MD010, no-hard-tabs)


767-767: Column: 1
Hard tabs

(MD010, no-hard-tabs)


768-768: Column: 1
Hard tabs

(MD010, no-hard-tabs)


769-769: Column: 1
Hard tabs

(MD010, no-hard-tabs)


770-770: Column: 1
Hard tabs

(MD010, no-hard-tabs)


771-771: Column: 1
Hard tabs

(MD010, no-hard-tabs)


772-772: Column: 1
Hard tabs

(MD010, no-hard-tabs)


773-773: Column: 1
Hard tabs

(MD010, no-hard-tabs)


774-774: Column: 1
Hard tabs

(MD010, no-hard-tabs)


775-775: Column: 1
Hard tabs

(MD010, no-hard-tabs)


776-776: Column: 1
Hard tabs

(MD010, no-hard-tabs)


778-778: Column: 1
Hard tabs

(MD010, no-hard-tabs)


779-779: Column: 1
Hard tabs

(MD010, no-hard-tabs)


780-780: Column: 1
Hard tabs

(MD010, no-hard-tabs)


781-781: Column: 1
Hard tabs

(MD010, no-hard-tabs)


783-783: Column: 1
Hard tabs

(MD010, no-hard-tabs)


784-784: Column: 1
Hard tabs

(MD010, no-hard-tabs)


785-785: Column: 1
Hard tabs

(MD010, no-hard-tabs)


789-789: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🔇 Additional comments (7)
mermaid/arch/icon.go (1)

10-18: Verify icon string values against Mermaid documentation.

Let's ensure the icon string values match Mermaid's supported icon syntax.

✅ Verification successful

Icon values are correctly used in Mermaid architecture diagrams

Based on the test file evidence, the icon values are being used correctly in Mermaid's architecture-beta syntax. The test cases demonstrate successful diagram generation with these icons:

  • IconDisk ("disk") is used for disk services
  • IconInternet ("internet") is used for gateway services
  • IconCloud ("cloud") is used for group elements

The test assertions pass and validate the correct Mermaid syntax output, confirming these icon values are compatible with Mermaid's architecture diagram specification.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for Mermaid documentation or tests that validate these icon values

# Look for Mermaid documentation files
fd -e md -e txt . | xargs rg -l "mermaid.*icon"

# Look for test files that might validate these icons
fd -e go | xargs rg -l "Icon.*Test"

Length of output: 87


Script:

#!/bin/bash
# Let's try a broader search for icon-related code and tests

# Search for icon-related tests
rg -l "func.*Test.*Icon" 

# Search for icon validation or usage
rg -l "Icon.*=.*\"" 

# Search for any documentation mentioning mermaid icons
rg -l "mermaid.*icons?"

# Look specifically in the arch package tests
fd "arch.*test.go$"

Length of output: 150


Script:

#!/bin/bash
# Let's examine the architecture test file and look for icon usage/validation

# Check architecture_test.go for icon usage
cat mermaid/arch/architecture_test.go

# Let's also check if there are any icon-related error messages or validations
rg "Icon.*invalid|invalid.*Icon" -A 2 -B 2

Length of output: 4343

mermaid/arch/group.go (1)

5-10: LGTM! Well-documented and properly implemented.

The implementation is clean and follows good practices:

  • Clear documentation with syntax example
  • Proper method chaining
  • Consistent indentation
doc/architecture/main.go (1)

1-1: Reconsider build constraint necessity

The build constraint //go:build linux || darwin seems unnecessary as this code should work on any OS that can run Go.

mermaid/arch/architecture_test.go (2)

1-4: LGTM! Clear package documentation.

The package documentation clearly indicates this is a beta feature and warns about potential specification changes.


14-16: LGTM! Good test setup.

Using t.Parallel() at the test function level is a good practice for concurrent test execution.

README.md (2)

678-681: LGTM! Clear feature introduction.

The new section clearly introduces the architecture diagram feature and properly references the Mermaid documentation.


682-786: Replace hard tabs with spaces in code example.

The code example uses hard tabs which should be replaced with spaces for consistent formatting across different editors.

✅ Verification successful

Let me verify the exact location and context of tabs in the README.md file.


Hard tabs found in code examples throughout README.md

The code examples in README.md consistently use hard tabs for indentation. Since these are example code blocks meant for documentation, they should use spaces for better rendering consistency across different platforms and editors.

  • Lines 685-786: Architecture diagram example uses tabs
  • Lines 49-94: Basic markdown example uses tabs
  • Lines 156-175: Go generate example uses tabs
  • Multiple other code examples throughout the file also use tabs
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for hard tabs in the code example
rg -l '\t' README.md

Length of output: 32


Script:

#!/bin/bash
# Check for tabs specifically in the code block section
rg -U --line-number '\t' README.md -A 1 -B 1

Length of output: 12061

🧰 Tools
🪛 Markdownlint (0.37.0)

686-686: Column: 1
Hard tabs

(MD010, no-hard-tabs)


687-687: Column: 1
Hard tabs

(MD010, no-hard-tabs)


689-689: Column: 1
Hard tabs

(MD010, no-hard-tabs)


690-690: Column: 1
Hard tabs

(MD010, no-hard-tabs)


696-696: Column: 1
Hard tabs

(MD010, no-hard-tabs)


697-697: Column: 1
Hard tabs

(MD010, no-hard-tabs)


698-698: Column: 1
Hard tabs

(MD010, no-hard-tabs)


699-699: Column: 1
Hard tabs

(MD010, no-hard-tabs)


700-700: Column: 1
Hard tabs

(MD010, no-hard-tabs)


702-702: Column: 1
Hard tabs

(MD010, no-hard-tabs)


703-703: Column: 1
Hard tabs

(MD010, no-hard-tabs)


704-704: Column: 1
Hard tabs

(MD010, no-hard-tabs)


705-705: Column: 1
Hard tabs

(MD010, no-hard-tabs)


706-706: Column: 1
Hard tabs

(MD010, no-hard-tabs)


707-707: Column: 1
Hard tabs

(MD010, no-hard-tabs)


708-708: Column: 1
Hard tabs

(MD010, no-hard-tabs)


709-709: Column: 1
Hard tabs

(MD010, no-hard-tabs)


710-710: Column: 1
Hard tabs

(MD010, no-hard-tabs)


711-711: Column: 1
Hard tabs

(MD010, no-hard-tabs)


712-712: Column: 1
Hard tabs

(MD010, no-hard-tabs)


713-713: Column: 1
Hard tabs

(MD010, no-hard-tabs)


714-714: Column: 1
Hard tabs

(MD010, no-hard-tabs)


715-715: Column: 1
Hard tabs

(MD010, no-hard-tabs)


716-716: Column: 1
Hard tabs

(MD010, no-hard-tabs)


717-717: Column: 1
Hard tabs

(MD010, no-hard-tabs)


718-718: Column: 1
Hard tabs

(MD010, no-hard-tabs)


719-719: Column: 1
Hard tabs

(MD010, no-hard-tabs)


720-720: Column: 1
Hard tabs

(MD010, no-hard-tabs)


721-721: Column: 1
Hard tabs

(MD010, no-hard-tabs)


722-722: Column: 1
Hard tabs

(MD010, no-hard-tabs)


723-723: Column: 1
Hard tabs

(MD010, no-hard-tabs)


724-724: Column: 1
Hard tabs

(MD010, no-hard-tabs)


725-725: Column: 1
Hard tabs

(MD010, no-hard-tabs)


726-726: Column: 1
Hard tabs

(MD010, no-hard-tabs)


727-727: Column: 1
Hard tabs

(MD010, no-hard-tabs)


728-728: Column: 1
Hard tabs

(MD010, no-hard-tabs)


729-729: Column: 1
Hard tabs

(MD010, no-hard-tabs)


730-730: Column: 1
Hard tabs

(MD010, no-hard-tabs)


731-731: Column: 1
Hard tabs

(MD010, no-hard-tabs)


732-732: Column: 1
Hard tabs

(MD010, no-hard-tabs)


733-733: Column: 1
Hard tabs

(MD010, no-hard-tabs)


734-734: Column: 1
Hard tabs

(MD010, no-hard-tabs)


735-735: Column: 1
Hard tabs

(MD010, no-hard-tabs)


736-736: Column: 1
Hard tabs

(MD010, no-hard-tabs)


737-737: Column: 1
Hard tabs

(MD010, no-hard-tabs)


738-738: Column: 1
Hard tabs

(MD010, no-hard-tabs)


739-739: Column: 1
Hard tabs

(MD010, no-hard-tabs)


740-740: Column: 1
Hard tabs

(MD010, no-hard-tabs)


741-741: Column: 1
Hard tabs

(MD010, no-hard-tabs)


742-742: Column: 1
Hard tabs

(MD010, no-hard-tabs)


743-743: Column: 1
Hard tabs

(MD010, no-hard-tabs)


744-744: Column: 1
Hard tabs

(MD010, no-hard-tabs)


745-745: Column: 1
Hard tabs

(MD010, no-hard-tabs)


746-746: Column: 1
Hard tabs

(MD010, no-hard-tabs)


747-747: Column: 1
Hard tabs

(MD010, no-hard-tabs)


748-748: Column: 1
Hard tabs

(MD010, no-hard-tabs)


749-749: Column: 1
Hard tabs

(MD010, no-hard-tabs)


750-750: Column: 1
Hard tabs

(MD010, no-hard-tabs)


751-751: Column: 1
Hard tabs

(MD010, no-hard-tabs)


752-752: Column: 1
Hard tabs

(MD010, no-hard-tabs)


753-753: Column: 1
Hard tabs

(MD010, no-hard-tabs)


754-754: Column: 1
Hard tabs

(MD010, no-hard-tabs)


755-755: Column: 1
Hard tabs

(MD010, no-hard-tabs)


756-756: Column: 1
Hard tabs

(MD010, no-hard-tabs)


757-757: Column: 1
Hard tabs

(MD010, no-hard-tabs)


758-758: Column: 1
Hard tabs

(MD010, no-hard-tabs)


759-759: Column: 1
Hard tabs

(MD010, no-hard-tabs)


760-760: Column: 1
Hard tabs

(MD010, no-hard-tabs)


761-761: Column: 1
Hard tabs

(MD010, no-hard-tabs)


762-762: Column: 1
Hard tabs

(MD010, no-hard-tabs)


763-763: Column: 1
Hard tabs

(MD010, no-hard-tabs)


764-764: Column: 1
Hard tabs

(MD010, no-hard-tabs)


765-765: Column: 1
Hard tabs

(MD010, no-hard-tabs)


766-766: Column: 1
Hard tabs

(MD010, no-hard-tabs)


767-767: Column: 1
Hard tabs

(MD010, no-hard-tabs)


768-768: Column: 1
Hard tabs

(MD010, no-hard-tabs)


769-769: Column: 1
Hard tabs

(MD010, no-hard-tabs)


770-770: Column: 1
Hard tabs

(MD010, no-hard-tabs)


771-771: Column: 1
Hard tabs

(MD010, no-hard-tabs)


772-772: Column: 1
Hard tabs

(MD010, no-hard-tabs)


773-773: Column: 1
Hard tabs

(MD010, no-hard-tabs)


774-774: Column: 1
Hard tabs

(MD010, no-hard-tabs)


775-775: Column: 1
Hard tabs

(MD010, no-hard-tabs)


776-776: Column: 1
Hard tabs

(MD010, no-hard-tabs)


778-778: Column: 1
Hard tabs

(MD010, no-hard-tabs)


779-779: Column: 1
Hard tabs

(MD010, no-hard-tabs)


780-780: Column: 1
Hard tabs

(MD010, no-hard-tabs)


781-781: Column: 1
Hard tabs

(MD010, no-hard-tabs)


783-783: Column: 1
Hard tabs

(MD010, no-hard-tabs)


784-784: Column: 1
Hard tabs

(MD010, no-hard-tabs)


785-785: Column: 1
Hard tabs

(MD010, no-hard-tabs)

mermaid/arch/service.go Show resolved Hide resolved
Comment on lines +12 to +16
// ServiceInGroup adds a service in a group to the architecture diagram.
func (a *Architecture) ServiceInGroup(serviceID string, icon Icon, title, groupID string) *Architecture {
a.body = append(a.body, fmt.Sprintf(" service %s(%s)[%s] in %s", serviceID, icon, title, groupID))
return a
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Protect against Mermaid syntax injection

The ServiceInGroup method directly interpolates user input into the Mermaid syntax string. This could lead to syntax injection if inputs contain special Mermaid characters.

Consider:

  1. Adding input validation for groupID
  2. Escaping special characters in all inputs
  3. Adding error handling for invalid inputs

mermaid/arch/junction.go Show resolved Hide resolved
mermaid/arch/group_test.go Show resolved Hide resolved
Comment on lines +57 to +68
// EdgesInAnothorGroup adds a string to connect two services in another group.
// Syntax: {serviceId}{{group}}:{T|B|L|R} {<}?--{>}? {T|B|L|R}:{serviceId}{{group}}
func (a *Architecture) EdgesInAnothorGroup(from, to Edge) *Architecture {
a.body = append(
a.body,
fmt.Sprintf(" %s{group}:%s %s--%s %s:%s{group}",
from.ServiceID, from.Position, from.Arrow,
to.Arrow, to.Position, to.ServiceID,
),
)
return a
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix typo in method name and enhance validation

  1. The method name has a typo: "Anothor" should be "Another"
  2. Consider adding validation for Edge fields
-func (a *Architecture) EdgesInAnothorGroup(from, to Edge) *Architecture {
+func (a *Architecture) EdgesInAnotherGroup(from, to Edge) *Architecture {
+	if err := validateEdge(from); err != nil {
+		a.err = fmt.Errorf("invalid 'from' edge: %w", err)
+		return a
+	}
+	if err := validateEdge(to); err != nil {
+		a.err = fmt.Errorf("invalid 'to' edge: %w", err)
+		return a
+	}
 	a.body = append(
 		a.body,
 		fmt.Sprintf("    %s{group}:%s %s--%s %s:%s{group}",

Add this validation helper:

func validateEdge(e Edge) error {
	if e.ServiceID == "" {
		return fmt.Errorf("service ID is required")
	}
	if e.Position == "" {
		return fmt.Errorf("position is required")
	}
	return nil
}

Comment on lines +16 to +22
func main() {
f, err := os.Create("generated.md")
if err != nil {
panic(err)
}
defer f.Close()

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Replace panic with proper error handling

Using panic for error handling is not recommended. Consider returning errors instead.

-func main() {
+func run() error {
 	f, err := os.Create("generated.md")
 	if err != nil {
-		panic(err)
+		return fmt.Errorf("failed to create file: %w", err)
 	}
 	defer f.Close()

 	// ... diagram creation ...

 	err = markdown.NewMarkdown(f).
 		H2("Architecture Diagram").
 		CodeBlocks(markdown.SyntaxHighlightMermaid, diagram).
 		Build()
 	if err != nil {
-		panic(err)
+		return fmt.Errorf("failed to build markdown: %w", err)
 	}
+	return nil
+}
+
+func main() {
+	if err := run(); err != nil {
+		fmt.Fprintf(os.Stderr, "Error: %v\n", err)
+		os.Exit(1)
+	}
 }

Also applies to: 99-106

@nao1215 nao1215 merged commit 09f9d46 into main Dec 18, 2024
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant