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

refactor(makefile): reorganize tool installation #73

Merged
merged 1 commit into from
Apr 1, 2025
Merged

Conversation

flc1125
Copy link
Member

@flc1125 flc1125 commented Apr 1, 2025

Summary by CodeRabbit

  • New Features
    • Introduced sample applications demonstrating API client usage and webhook event processing.
    • Added functionality to retrieve the current version programmatically.
  • Tests
    • Implemented tests to ensure versioning adheres to semantic standards.
  • Chores
    • Enhanced build and dependency management processes.
    • Updated configuration for file tracking to improve project consistency.

@dosubot dosubot bot added the size:XL This PR changes 500-999 lines, ignoring generated files. label Apr 1, 2025
Copy link

coderabbitai bot commented Apr 1, 2025

Walkthrough

The pull request modifies the repository’s configuration and build process and introduces new modules and features. The .gitignore file is updated to stop ignoring _example files and to ignore the .tools directory. The Makefile is overhauled with new variables and targets for building, testing, linting, and module management. Several new Go modules and files are introduced for basic examples, webhook functionality, tool management, and versioning, along with a configuration file (versions.yaml). A dependency is also removed from the main go.mod.

Changes

File(s) Change Summary
.gitignore Removed ignore entry for _example and added entry for .tools.
Makefile Restructured build process with new variables and targets for module discovery, tool building, testing, linting, and pre-release tasks.
go.mod, examples/.../go.mod,
internal/tools/go.mod, webhook/go.mod
Introduced and updated module files with declarations, dependency changes, replace directives, and Go/toolchain version specifications.
examples/.../main.go,
internal/tools/main.go
Added new Go files: one for initializing a TAPD client and another for handling webhooks and tool integrations.
version.go,
version_test.go
Added a new Version function returning "0.10.0" and a corresponding test to validate semver compliance.
versions.yaml Added a new configuration file defining module sets (stable version v0.10.0) and listing excluded modules.

Sequence Diagram(s)

sequenceDiagram
    participant Main as Basic Example Main
    participant Client as TAPD Client
    participant LabelService as LabelService
    Note over Main: Initialize TAPD client with credentials
    Main->>Client: Create client
    Client-->>Main: Client instance or error
    Main->>LabelService: Call GetLabels(context, request)
    LabelService-->>Main: Return labels or error
    Main->>Main: Log formatted labels
Loading
sequenceDiagram
    participant HTTP as HTTP Server
    participant Dispatcher as Webhook Dispatcher
    participant Listener as StoreUpdateListener
    Note over HTTP: Receives request at /webhook
    HTTP->>Dispatcher: Dispatch webhook request
    Dispatcher->>Listener: Invoke OnStoryUpdate(context, event)
    Listener-->>Dispatcher: Return nil (success)
    Dispatcher-->>HTTP: Response ("ok")
    HTTP->>HTTP: Log event and errors if any
Loading

Suggested labels

size:L

Poem

Oh, what a hop of change today,
With modules dancing in a brilliant array,
Tools and tests now neatly aligned,
Code paths and builds perfectly defined.
I, a happy rabbit, skip with glee,
Celebrating clean code for you and me!
🐰✨

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (1.64.8)

Error: you are using a configuration file for golangci-lint v2 with golangci-lint v1: please use golangci-lint v2
Failed executing command with error: you are using a configuration file for golangci-lint v2 with golangci-lint v1: please use golangci-lint v2

✨ Finishing Touches
  • 🔥 Error while generating docstrings. (🔄 Check again to generate docstrings again)

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
🪧 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.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @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

codecov bot commented Apr 1, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Files with missing lines Coverage Δ
version.go 100.00% <100.00%> (ø)

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@dosubot dosubot bot added the go Pull requests that update Go code label Apr 1, 2025
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: 3

🧹 Nitpick comments (10)
version.go (1)

1-5: LGTM! Version function provides a clear way to access the package version.

The function follows a common pattern for exposing version information in Go libraries.

Consider using build-time version injection or a central version constant shared across the codebase to avoid potential inconsistencies when updating versions in the future:

package tapd

-func Version() string {
-	return "0.10.0"
-}
+// Version returns the current version of the tapd package.
+// This value may be overridden at build time.
+func Version() string {
+	return version
+}
+
+// version is the current version of the tapd package.
+var version = "0.10.0"
examples/basic/main.go (3)

11-14: Consider using environment variables for credentials in the example.

Even in examples, it's a good practice to show how to securely handle credentials through environment variables rather than hard-coding them.

-	client, err := tapd.NewClient("client_id", "client_secret")
+	// In a real application, credentials should be retrieved from environment variables or a secure configuration
+	clientID := os.Getenv("TAPD_CLIENT_ID")
+	if clientID == "" {
+		clientID = "client_id" // Fallback for example purposes only
+	}
+	clientSecret := os.Getenv("TAPD_CLIENT_SECRET")
+	if clientSecret == "" {
+		clientSecret = "client_secret" // Fallback for example purposes only
+	}
+	
+	client, err := tapd.NewClient(clientID, clientSecret)

Don't forget to add "os" to the import statement:

import (
	"context"
	"log"
+	"os"

	"github.com/go-tapd/tapd"
)

17-19: Use a named constant instead of magic number with linter directive.

Using a named constant with a descriptive name is clearer than using a magic number with a linter directive.

+	// For demonstration purposes - replace with your actual workspace ID
+	const exampleWorkspaceID = 123456
+
	// example: get labels
	labels, _, err := client.LabelService.GetLabels(context.Background(), &tapd.GetLabelsRequest{
-		WorkspaceID: tapd.Ptr(123456), // nolint:mnd
+		WorkspaceID: tapd.Ptr(exampleWorkspaceID),
	})

20-24: Add more comprehensive error handling and response validation.

The example would be more instructive with validation of the response data beyond just checking for API errors.

	if err != nil {
		log.Fatal(err)
	}

-	log.Printf("labels: %+v", labels)
+	// Check if we received labels and display them
+	if len(labels) == 0 {
+		log.Println("No labels found for this workspace")
+	} else {
+		log.Printf("Found %d labels:", len(labels))
+		for i, label := range labels {
+			log.Printf("  %d. %s", i+1, label.Name)
+		}
+	}
internal/tools/go.mod (2)

5-10: Direct Dependencies Block Verification
The direct dependencies for the tooling (e.g. golangci-lint, gocovmerge, multimod) are clearly listed with fixed versions. Ensure that these versions remain in sync with your toolchain requirements over time.


12-220: Comprehensive Indirect Dependencies Listing
The indirect dependencies block is extensive and follows the standard format. It is recommended to periodically run "go mod tidy" to clean up any unused dependencies and confirm that all indirect versions are current.

examples/webhook/go.mod (1)

7-10: Replace Directives for Local Development
The replace directives correctly point to local directories for the main module and its webhook subpackage. Double-check that the relative paths (../../ and ../../webhook/) are accurate relative to the location of this file.

Makefile (3)

5-7: Go Module Discovery Variables
The variables ALL_GO_MOD_DIRS, ROOT_GO_MOD_DIRS, and ALL_COVERAGE_MOD_DIRS are set up using find and grep. One point to note is that the grep pattern ' ^./example' (line 7) may not match directories prefixed with ./examples (plural) if such examples are intended to be excluded. Consider verifying the regex pattern to ensure it meets the intended directory filtering.


69-82: Test-Coverage Workflow
The test-coverage target is comprehensive—it iterates over module directories to generate coverage data and then merges them using gocovmerge. The inline loop and nested commands are complex; confirm that error handling within the loop is sufficient (note that set -e is used) and that coverage reports are reliably produced in your CI environment.


109-117: Working Tree Cleanliness Check
The check-clean-work-tree target uses git diff --quiet to verify a clean state. This is a useful pre-commit check, though you might consider whether it should also check for untracked files if that matters in your workflow.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 85fe6c4 and 0b013b3.

⛔ Files ignored due to path filters (5)
  • examples/basic/go.sum is excluded by !**/*.sum
  • examples/webhook/go.sum is excluded by !**/*.sum
  • go.sum is excluded by !**/*.sum
  • internal/tools/go.sum is excluded by !**/*.sum
  • webhook/go.sum is excluded by !**/*.sum
📒 Files selected for processing (13)
  • .gitignore (1 hunks)
  • Makefile (1 hunks)
  • examples/basic/go.mod (1 hunks)
  • examples/basic/main.go (1 hunks)
  • examples/webhook/go.mod (1 hunks)
  • examples/webhook/main.go (1 hunks)
  • go.mod (0 hunks)
  • internal/tools/go.mod (1 hunks)
  • internal/tools/main.go (1 hunks)
  • version.go (1 hunks)
  • version_test.go (1 hunks)
  • versions.yaml (1 hunks)
  • webhook/go.mod (1 hunks)
💤 Files with no reviewable changes (1)
  • go.mod
🧰 Additional context used
🧬 Code Definitions (1)
version_test.go (1)
version.go (1)
  • Version (3-5)
🔇 Additional comments (23)
webhook/go.mod (1)

1-5: LGTM! The module structure follows standard Go practices.

The module definition with the replace directive is correctly set up for local development.

.gitignore (1)

17-17: LGTM! Adding .tools to gitignore aligns with the PR objective.

Ignoring the .tools directory is a good practice since it will likely contain built/installed tools that shouldn't be committed to the repository.

versions.yaml (1)

1-10: LGTM! Clean versioning configuration structure.

The module-sets configuration provides a clear way to manage versioning across the project, with appropriate exclusions for internal tools and examples.

internal/tools/main.go (1)

1-11: Well-structured tool dependency management

This file follows Go best practices for managing tool dependencies. The build tags ensure these tools are only included when explicitly requested, and blank imports make sure the tools are versioned with the codebase without being included in the final binary.

version_test.go (1)

11-20: Well-designed semantic versioning test

The test is properly implemented to ensure that the project's version adheres to semantic versioning standards using an authoritative regex pattern. This helps maintain consistent versioning practices across the project.

examples/basic/go.mod (1)

1-13: Properly configured example module

The module file is correctly set up with appropriate version requirements and a local replace directive, which is ideal for example code that references the parent module.

internal/tools/go.mod (1)

1-4: Module Declaration and Go Version Check
The module path and Go version are declared according to Go conventions. This new module file cleanly sets up the tools submodule.

examples/webhook/go.mod (2)

1-5: Module Declaration and Toolchain Specification
The module is properly declared for the webhook example and specifies both the Go version and an explicit toolchain version. Note that the specified Go version (1.23.0) differs from the toolchain (go1.24.1); please verify that this distinction is intentional and that it meets the project’s build requirements.


12-20: Dependency Declarations and Indirect Dependencies Overview
The file correctly requires the github.com/go-tapd/tapd/webhook dependency and lists the necessary indirect dependencies. Running "go mod tidy" periodically can help keep these up-to-date.

Makefile (14)

2-3: Core Variables Initialization
The definition of TOOLS_MOD_DIR and ROOT_DIR is clear and correctly uses shell commands to determine absolute paths. This provides a robust basis for subsequent path derivations.


9-10: Tool and Timeout Variables
The settings for the Go command (GO = go) and the default timeout are straightforward and appropriate.


14-20: Tools Build Rule Configuration
The targets for creating the .tools directory and building individual tool binaries (using a generic target that relies on the PACKAGE variable) are well structured. This modular approach enables easy extension for additional tools.


23-33: Tool-Specific Binary Definitions
The assignments for GOLANGCI_LINT, GORELEASE, GOCOVMERGE, and MULTIMOD, along with their respective package values, are clearly defined. The reuse of the common build rule (from line 18) keeps the Makefile DRY.


35-37: Tools Target Aggregation
The tools target correctly aggregates the build rules for all required tool binaries. This makes executing the tool build process simple and centralized.


39-49: Build Target Strategy
The build target compiles all Go modules found in the filtered root directories and outputs binaries under a central bin folder. Ensure that overlapping build outputs (if any) are handled correctly in your project.


50-67: Test Targets Implementation
The test targets take advantage of parameterized arguments for different test scenarios. The use of $(GO) list ./... | xargs $(GO) test ... is standard; however, consider potential edge cases (e.g., directory names with spaces) depending on your repository structure.


84-93: Linting Targets Configuration
The lint targets, including golangci-lint and its fix variant, are well organized. The echo messages and directory switching make the process comprehensible. Ensure that this setup works consistently across different modules.


94-101: go-mod-tidy and Lint-Modules Integration
The targets for tidying go.mod files and enforcing module linting are straightforward. The use of -compat=1.22.0 in the mod tidy command may need review to ensure compatibility with all modules.


105-107: Aggregate Lint Target
The aggregate lint target properly depends on both module tidying and linting via golangci-lint, ensuring comprehensive code checks.


119-126: gorelease Target Execution
The gorelease target iterates over module directories and executes the release command. The fallback with || echo "" helps prevent build failure, but be mindful that it might mask errors during release operations.


127-130: Module Verification Target
The verify-mods target appropriately calls $(MULTIMOD) verify to check module dependencies.


131-135: Pre-release Environment Validation
The prerelease target includes a guard for the MODSET environment variable, which is essential to prevent misconfiguration. This extra check strengthens the release process.


137-141: Tag Addition with Environment Guard
The add-tags target similarly ensures that MODSET is set before attempting to tag the release. This consistency in environment checking is commendable.

w.Write([]byte("ok")) //nolint:errcheck
})

http.ListenAndServe(":8080", srv) //nolint:errcheck
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Handle server startup errors

In a real application, even an example, you should properly handle HTTP server startup errors as they indicate critical failures.

-http.ListenAndServe(":8080", srv) //nolint:errcheck
+log.Println("Starting server on :8080")
+if err := http.ListenAndServe(":8080", srv); err != nil {
+	log.Fatalf("Server failed to start: %v", err)
+}
📝 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
http.ListenAndServe(":8080", srv) //nolint:errcheck
log.Println("Starting server on :8080")
if err := http.ListenAndServe(":8080", srv); err != nil {
log.Fatalf("Server failed to start: %v", err)
}

Comment on lines +19 to +22
dispatcher := webhook.NewDispatcher(
webhook.WithRegisters(&StoreUpdateListener{}),
)
dispatcher.Registers(&StoreUpdateListener{})
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove duplicate listener registration

The StoreUpdateListener is registered twice - once in the constructor and again with the Registers method. This is redundant and could cause unexpected behavior.

 dispatcher := webhook.NewDispatcher(
 	webhook.WithRegisters(&StoreUpdateListener{}),
 )
-dispatcher.Registers(&StoreUpdateListener{})
📝 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
dispatcher := webhook.NewDispatcher(
webhook.WithRegisters(&StoreUpdateListener{}),
)
dispatcher.Registers(&StoreUpdateListener{})
dispatcher := webhook.NewDispatcher(
webhook.WithRegisters(&StoreUpdateListener{}),
)

Comment on lines +25 to +31
srv.HandleFunc("/webhook", func(w http.ResponseWriter, r *http.Request) {
log.Println("Received webhook request")
if err := dispatcher.DispatchRequest(r); err != nil {
log.Println(err)
}
w.Write([]byte("ok")) //nolint:errcheck
})
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add HTTP method check and improve error handling

The webhook endpoint should validate that it only receives POST requests, and the response writing error should be properly handled.

 srv.HandleFunc("/webhook", func(w http.ResponseWriter, r *http.Request) {
 	log.Println("Received webhook request")
+	if r.Method != http.MethodPost {
+		w.WriteHeader(http.StatusMethodNotAllowed)
+		if _, err := w.Write([]byte("method not allowed")); err != nil {
+			log.Printf("Error writing response: %v", err)
+		}
+		return
+	}
 	if err := dispatcher.DispatchRequest(r); err != nil {
 		log.Println(err)
 	}
-	w.Write([]byte("ok")) //nolint:errcheck
+	if _, err := w.Write([]byte("ok")); err != nil {
+		log.Printf("Error writing response: %v", err)
+	}
 })
📝 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
srv.HandleFunc("/webhook", func(w http.ResponseWriter, r *http.Request) {
log.Println("Received webhook request")
if err := dispatcher.DispatchRequest(r); err != nil {
log.Println(err)
}
w.Write([]byte("ok")) //nolint:errcheck
})
srv.HandleFunc("/webhook", func(w http.ResponseWriter, r *http.Request) {
log.Println("Received webhook request")
if r.Method != http.MethodPost {
w.WriteHeader(http.StatusMethodNotAllowed)
if _, err := w.Write([]byte("method not allowed")); err != nil {
log.Printf("Error writing response: %v", err)
}
return
}
if err := dispatcher.DispatchRequest(r); err != nil {
log.Println(err)
}
if _, err := w.Write([]byte("ok")); err != nil {
log.Printf("Error writing response: %v", err)
}
})

@flc1125 flc1125 merged commit bb0b1a0 into master Apr 1, 2025
13 checks passed
@flc1125 flc1125 deleted the monorepo branch April 1, 2025 14:43
Copy link

coderabbitai bot commented Apr 1, 2025

Caution

An unexpected error occurred while opening a pull request: Not Found - https://docs.github.com/rest/git/refs#get-a-reference

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
go Pull requests that update Go code size:XL This PR changes 500-999 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant