-
Couldn't load subscription status.
- Fork 1.6k
📖 Add docs: custom markers for unsupported file extensions #5107
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
base: master
Are you sure you want to change the base?
📖 Add docs: custom markers for unsupported file extensions #5107
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: nerdeveloper The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
|
Hi @nerdeveloper. Thanks for your PR. I'm waiting for a kubernetes-sigs member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
ddb8cdb to
161acff
Compare
| - You're building an **external plugin** for a language not natively supported by Kubebuilder | ||
| - You want to scaffold files with custom extensions (`.rs`, `.java`, `.tpl`, `.py`, etc.) | ||
| - Your file extensions aren't (and shouldn't be) part of the core `commentsByExt` map | ||
| - You need to maintain scaffolding markers in non-Go files |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the documentation could be How to create Custom Markers.
For those who use Kubebuilder as a library, it would be possible to create their own custom markers, regardless of whether it is for an extension valid or not for Golang projects.
So, it would not only be valid for external references
| builder.WriteString(":") | ||
| } | ||
| return builder.String() | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you let me know if you tested this example?
Can it work without any change in the code at this moment?
Is the code covered with tests to ensure that this example would be possible?
| } | ||
| ``` | ||
|
|
||
| ## Complete Example: Rust Plugin with Custom Markers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need all those examples?
Could we not have only 1 example?
How could we simplify the doc and its maintainability?
Just to share what is required
| ## Best Practices | ||
|
|
||
| 1. **Use Clear Prefixes**: Choose a unique prefix for your plugin to avoid conflicts (e.g., `+rust:scaffold:`, `+java:scaffold:`) | ||
|
|
||
| 2. **Handle Comments Correctly**: Different languages have different comment syntax. Make sure to map the correct comment style for each file extension. | ||
|
|
||
| 3. **Error Handling**: Always validate file extensions and return clear error messages when unsupported files are encountered. | ||
|
|
||
| 4. **Maintain Compatibility**: When possible, follow the same patterns as Kubebuilder's core marker system to maintain consistency. | ||
|
|
||
| 5. **Document Your Markers**: Clearly document what markers your plugin supports and where they should be placed. | ||
|
|
||
| 6. **Testing**: Test your marker implementation with various file types and edge cases. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Best Practices is something subjective, I think it's better to avoid this term.
| } | ||
| ``` | ||
|
|
||
| ## Conclusion |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please review the other documentation we have?
We do not use a conclusion. We should always follow the same layout and standards.
|
Hi @camilamacedo86, Thank you for the review feedback! I've updated the documentation to address your comments: ✅ Changed title to "Creating Custom Markers" (broader scope, not just for unsupported extensions) Regarding testing: I performed minimal testing of the marker generation logic by creating a standalone Go program that tests the core marker creation code. The test confirms:
However, I have NOT tested the complete integration with external plugins end-to-end (the full example with templates and plugin integration). Question: What would you prefer for this documentation?
Please let me know your preference, and I'll update accordingly! |
Shows how to use Kubebuilder as a library to create custom marker support for external plugins with non-Go file extensions like .rs, .java, .py
161acff to
51faf4e
Compare
| ## Key Considerations | ||
|
|
||
| 1. **Unique Prefixes**: Choose a unique prefix for your plugin to avoid conflicts (e.g., `+rust:scaffold:`, `+java:scaffold:`) | ||
|
|
||
| 2. **Comment Syntax**: Different languages have different comment syntax. Ensure you map the correct comment style for each file extension | ||
|
|
||
| 3. **Error Handling**: Validate file extensions and return clear error messages for unsupported files | ||
|
|
||
| 4. **Testing**: Test your marker implementation with various scenarios to ensure reliability |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think all is great !!!
Well done 👍 Good job but wdyt about we remove this part?
I think is best we avoid adding things that are more opinionated and keep it as low verbose as possible.
|
|
||
| Here's how to implement custom markers for Rust files (`.rs`). This same pattern can be applied to any file extension. | ||
|
|
||
| ### Define Your Marker Type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you test those examples?
Because when it was raised seems like it was missing externalise something.
Is that working properly?
If so, could you please share in the description the POC / tests made?
- Remove Key Considerations section per reviewer feedback - Update external plugin example to match current API pattern - Fix external plugin integration code to use JSON/STDIN communication - Simplify template example to be more realistic for external plugins - Merge latest changes from master branch Addresses feedback from PR review comments
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds comprehensive documentation for creating custom markers in Kubebuilder when working with unsupported file extensions. It demonstrates how to use Kubebuilder as a library for external plugins, enabling support for languages beyond Go (such as Rust, Java, and Python) by implementing custom marker systems.
Key Changes:
- Adds complete guide for implementing custom markers for non-Go file extensions
- Provides working code examples for Rust-based external plugins
- Includes integration examples showing external plugin communication patterns
Reviewed Changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| docs/book/src/plugins/extending/custom-markers.md | New documentation file explaining custom marker implementation with Rust examples and external plugin integration |
| docs/book/src/SUMMARY.md | Adds table of contents entry for the new custom markers documentation |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| case "flags": | ||
| response = handleFlags(pluginRequest) | ||
| case "metadata": | ||
| response = handleMetadata(pluginRequest) |
Copilot
AI
Oct 27, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The example references handleFlags and handleMetadata functions that are not defined or shown in the documentation. Either provide these function implementations or remove these case statements to avoid confusion for readers trying to follow the example.
| case "flags": | |
| response = handleFlags(pluginRequest) | |
| case "metadata": | |
| response = handleMetadata(pluginRequest) |
|
|
||
| func handleInit(req *external.PluginRequest) external.PluginResponse { | ||
| // Create Rust file with custom markers | ||
| marker, _ := markers.NewRustMarker("src/main.rs", "imports") |
Copilot
AI
Oct 27, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error is silently discarded using blank identifier. In documentation examples, it's better to demonstrate proper error handling to avoid teaching bad practices. Consider handling the error or adding a comment explaining why it's safe to ignore in this specific context.
| marker, _ := markers.NewRustMarker("src/main.rs", "imports") | |
| marker, err := markers.NewRustMarker("src/main.rs", "imports") | |
| if err != nil { | |
| return external.PluginResponse{ | |
| Command: "init", | |
| Error: true, | |
| ErrorMsgs: []string{fmt.Sprintf("failed to create Rust marker: %v", err)}, | |
| } | |
| } |
How to Test This Implementation@camilamacedo86 Here are step-by-step instructions to test the custom marker implementation: Quick Test1. Test the core marker functionality: # Create a test file in any directory
cat > test_markers.go << 'EOF'
package main
import (
"fmt"
"path/filepath"
"strings"
)
const RustPluginPrefix = "+rust:scaffold:"
type RustMarker struct {
prefix string
comment string
value string
}
func NewRustMarker(path string, value string) (RustMarker, error) {
ext := filepath.Ext(path)
if ext != ".rs" {
return RustMarker{}, fmt.Errorf("expected .rs file, got %s", ext)
}
return RustMarker{
prefix: formatPrefix(RustPluginPrefix),
comment: "//",
value: value,
}, nil
}
func (m RustMarker) String() string {
return m.comment + " " + m.prefix + m.value
}
func formatPrefix(prefix string) string {
trimmed := strings.TrimSpace(prefix)
var builder strings.Builder
if !strings.HasPrefix(trimmed, "+") {
builder.WriteString("+")
}
builder.WriteString(trimmed)
if !strings.HasSuffix(trimmed, ":") {
builder.WriteString(":")
}
return builder.String()
}
func main() {
fmt.Println("Testing marker creation...")
marker, err := NewRustMarker("src/main.rs", "imports")
if err != nil {
fmt.Printf("Error: %v", err)
return
}
fmt.Printf("Generated marker: %s", marker.String())
// Test error case
_, err = NewRustMarker("main.go", "imports")
if err != nil {
fmt.Printf("\nCorrect error for Go file: %v", err)
}
}
EOF
# Run the test
go run test_markers.goExpected output: Verify External Plugin Imports2. Test that external plugin types are accessible: cat > test_external.go << 'EOF'
package main
import (
"fmt"
"sigs.k8s.io/kubebuilder/v4/pkg/plugin/external"
)
func main() {
var req external.PluginRequest
var resp external.PluginResponse
fmt.Printf("PluginRequest available: %T\n", req)
fmt.Printf("PluginResponse available: %T\n", resp)
fmt.Println("External plugin imports working!")
}
EOF
go run test_external.goExpected output: Clean Uprm test_markers.go test_external.go |
- Remove undefined function references (handleFlags, handleMetadata) - Add proper error handling instead of silently discarding errors - Keep external plugin example simple and focused on custom markers - Ensure all code examples are self-contained and functional Addresses Copilot PR review feedback
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
when all is good, i wil squash all of them into one commit |
Summary
Related
Test Plan