-
Couldn't load subscription status.
- Fork 71
Shareable Go package experiment in sdk-platform-java #3938
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: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| // Copyright 2025 Google LLC | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| // Package languagecontainer defines LanguageContainer interface and | ||
| // the Run function to execute commands within the container. | ||
| // TODO(b/447404382): Move this package to the https://github.com/googleapis/librarian | ||
| // GitHub repository once the interface is finalized. | ||
| // This package must not have any Java-specific implementation. | ||
| package languagecontainer | ||
|
|
||
| import ( | ||
| "context" | ||
| "log/slog" | ||
|
|
||
| "cloud.google.com/java/internal/librariangen/message" | ||
| ) | ||
|
|
||
| // GenerateCommandContext holds the context (the file system paths) for | ||
| // the generate command. The createGenerateContext function creates | ||
| // an instance of this by reading the command line flags and the | ||
| // default values. | ||
| type GenerateCommandContext struct { | ||
| } | ||
| type GenerateCommandEnv struct { | ||
| GenerateContext *GenerateCommandContext | ||
| GenerateRequest *message.GenerateRequest | ||
| } | ||
|
|
||
| type ConfigureCommandContext struct { | ||
| } | ||
|
|
||
| type ConfigureCommandEnv struct { | ||
| ConfigureContext *ConfigureCommandContext | ||
| ConfigureRequest *message.ConfigureRequest | ||
| } | ||
|
|
||
| // LanguageContainer defines the interface for language-specific container operations. | ||
| type LanguageContainer interface { | ||
| Generate(context.Context, *GenerateCommandEnv) error | ||
| Configure(context.Context, *ConfigureCommandEnv) (*message.ConfigureResponse, error) | ||
| // Other container functions like ReleaseInit and Build would also be part of the interface. | ||
| } | ||
|
|
||
| // Run would accept an implementation of the LanguageContainer interface. | ||
| func Run(args []string, container LanguageContainer) int { | ||
| // Logic to parse args and call the appropriate method on the container. | ||
| // For example, if args[1] is "generate": | ||
| // request := ... // unmarshal the request from the expected location | ||
| // err := container.Generate(context.Background(), request) | ||
| // ... | ||
| if len(args) < 1 { | ||
| panic("args must not be empty") | ||
| } | ||
| switch args[0] { | ||
| case "generate": | ||
| env := createGenerateEnv(args[1:]) | ||
| err := container.Generate(context.Background(), env) | ||
| if err != nil { | ||
| // TODO: Save it as a response file. | ||
| panic(err) | ||
| } | ||
|
Comment on lines
+69
to
+72
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using if err != nil {
// TODO: Save it as a response file.
slog.Error("librariangen: generate command failed", "error", err)
return 1
} |
||
| return 0 | ||
| case "configure": | ||
| env := createConfigureEnv(args[1:]) | ||
| resp, err := container.Configure(context.Background(), env) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
|
Comment on lines
+77
to
+79
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using if err != nil {
slog.Error("librariangen: configure command failed", "error", err)
return 1
} |
||
| // TODO: Save it as a response file. | ||
| _ = resp | ||
| return 0 | ||
| case "release-init": | ||
| slog.Warn("librariangen: release-init command is not yet implemented") | ||
| return 1 | ||
| case "build": | ||
| slog.Warn("librariangen: build command is not yet implemented") | ||
| return 1 | ||
| default: | ||
| slog.Error("librariangen: unknown command: %s (with flags %v)", args[0], args) | ||
| return 1 | ||
| } | ||
| return 0 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| } | ||
|
|
||
| // https://github.com/googleapis/librarian/blob/main/doc/language-onboarding.md#generate | ||
| func createGenerateEnv(args []string) *GenerateCommandEnv { | ||
| generateContext := createGenerateCommandContext(args) | ||
| return &GenerateCommandEnv{ | ||
| GenerateContext: generateContext, | ||
| } | ||
| } | ||
|
|
||
| func createGenerateCommandContext(args []string) *GenerateCommandContext { | ||
| // TODO: Parse args and create the context. | ||
| return &GenerateCommandContext{} | ||
| } | ||
|
|
||
| func createConfigureCommandContext(args []string) *ConfigureCommandContext { | ||
| // TODO: Parse args and create the context. | ||
| return &ConfigureCommandContext{} | ||
| } | ||
|
|
||
| func createConfigureEnv(args []string) *ConfigureCommandEnv { | ||
| configureContext := createConfigureCommandContext(args) | ||
| return &ConfigureCommandEnv{ | ||
| ConfigureContext: configureContext, | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -16,32 +16,42 @@ package main | |||||
|
|
||||||
| import ( | ||||||
| "context" | ||||||
| "errors" | ||||||
| "fmt" | ||||||
| "log/slog" | ||||||
| "os" | ||||||
| "strings" | ||||||
|
|
||||||
| "cloud.google.com/java/internal/librariangen/languagecontainer" | ||||||
| "cloud.google.com/java/internal/librariangen/message" | ||||||
| ) | ||||||
|
|
||||||
| const version = "0.1.0" | ||||||
|
|
||||||
| // main is the entrypoint for the librariangen CLI. | ||||||
| func main() { | ||||||
| os.Exit(runCLI(os.Args)) | ||||||
| // javaContainer implements the LanguageContainer interface for Java. | ||||||
| type javaContainer struct{} | ||||||
|
|
||||||
| func (c *javaContainer) Generate(context.Context, *languagecontainer.GenerateCommandEnv) error { | ||||||
| // Java-specific implementation for the "generate" command. | ||||||
| slog.Warn("librariangen: generate command is not yet implemented") | ||||||
|
|
||||||
| return nil | ||||||
| } | ||||||
|
|
||||||
| func runCLI(args []string) int { | ||||||
| func (c *javaContainer) Configure(ctx context.Context, | ||||||
| request *languagecontainer.ConfigureCommandEnv) (*message.ConfigureResponse, error) { | ||||||
| // Java-specific implementation for the "configure" command. | ||||||
| slog.Warn("librariangen: configure command is not yet implemented") | ||||||
| return nil, nil | ||||||
| } | ||||||
|
|
||||||
| // main is the entrypoint for the librariangen CLI. | ||||||
| func main() { | ||||||
| logLevel := parseLogLevel(os.Getenv("GOOGLE_SDK_JAVA_LOGGING_LEVEL")) | ||||||
| slog.SetDefault(slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ | ||||||
| Level: logLevel, | ||||||
| }))) | ||||||
| args := os.Args | ||||||
| slog.Info("librariangen: invoked", "args", args) | ||||||
| if err := run(context.Background(), args[1:]); err != nil { | ||||||
| slog.Error("librariangen: failed", "error", err) | ||||||
| return 1 | ||||||
| } | ||||||
| slog.Info("librariangen: finished successfully") | ||||||
| return 0 | ||||||
| container := javaContainer{} | ||||||
| os.Exit(languagecontainer.Run(os.Args, &container)) | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Suggested change
|
||||||
| } | ||||||
|
|
||||||
| func parseLogLevel(logLevelEnv string) slog.Level { | ||||||
|
|
@@ -54,42 +64,3 @@ func parseLogLevel(logLevelEnv string) slog.Level { | |||||
| return slog.LevelInfo | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| // run executes the appropriate command based on the CLI's invocation arguments. | ||||||
| // The idiomatic structure is `librariangen [command] [flags]`. | ||||||
| func run(ctx context.Context, args []string) error { | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||
| if len(args) < 1 { | ||||||
| return errors.New("librariangen: expected a command") | ||||||
| } | ||||||
|
|
||||||
| // The --version flag is a special case and not a command. | ||||||
| if args[0] == "--version" { | ||||||
| fmt.Println(version) | ||||||
| return nil | ||||||
| } | ||||||
|
|
||||||
| cmd := args[0] | ||||||
| flags := args[1:] | ||||||
|
|
||||||
| if strings.HasPrefix(cmd, "-") { | ||||||
| return fmt.Errorf("librariangen: command cannot be a flag: %s", cmd) | ||||||
| } | ||||||
|
|
||||||
| switch cmd { | ||||||
| case "generate": | ||||||
| slog.Warn("librariangen: generate command is not yet implemented") | ||||||
| return nil | ||||||
| case "release-init": | ||||||
| slog.Warn("librariangen: release-init command is not yet implemented") | ||||||
| return nil | ||||||
| case "configure": | ||||||
| slog.Warn("librariangen: configure command is not yet implemented") | ||||||
| return nil | ||||||
| case "build": | ||||||
| slog.Warn("librariangen: build command is not yet implemented") | ||||||
| return nil | ||||||
| default: | ||||||
| return fmt.Errorf("librariangen: unknown command: %s (with flags %s)", cmd, flags) | ||||||
| } | ||||||
|
|
||||||
| } | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| // Copyright 2025 Google LLC | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
|
|
||
| // Package message defines data types which the Librarian CLI and language | ||
| // containers exchange. | ||
| // There shouldn't be CLI-specific data type or language container-specific | ||
| // data types in this package. | ||
| // TODO(b/447404382): Move this package to the https://github.com/googleapis/librarian | ||
| // GitHub repository once the interface is finalized. | ||
| // This package must not have any Java-specific implementation. | ||
| package message | ||
|
|
||
| // GenerateRequest is the JSON message sent to the language container by | ||
| // the Librarian CLI when the "generate" command is invoked. | ||
| type GenerateRequest struct { | ||
| } | ||
|
|
||
| // GenerateResponse is the JSON message sent back to the Librarian CLI | ||
| // by the language container after processing the "generate" command. | ||
| type GenerateResponse struct { | ||
| } | ||
|
|
||
| // ConfigureRequest is the JSON message sent to the language container by | ||
| // the Librarian CLI when the "configure" command is invoked. | ||
| type ConfigureRequest struct { | ||
| } | ||
|
|
||
| // ConfigureResponse is the JSON message sent back to the Librarian CLI | ||
| // by the language container after processing the "configure" command. | ||
| type ConfigureResponse struct { | ||
| } |
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.
Panicking on invalid user input (like missing arguments) is ungraceful for a command-line tool. It's better to print an error message and exit with a non-zero status code. This provides a better user experience.