Skip to content

Conversation

@suztomo
Copy link
Member

@suztomo suztomo commented Oct 21, 2025

Introducing languagecontainer package.

  • New languagecontainer package: A new languagecontainer package has been introduced to encapsulate language-specific container operations and command execution logic, promoting modularity. This package parses the request JSON file and calls the
    corresponding implementation method in each language container. The languagecontainer package itself should not have language-specific implementation.

    • release-init command parsing: The languagecontainer.Run function now includes robust logic to parse release-init requests from JSON files, handle command-line flags, and invoke the ReleaseInit function.
    • Why isn't this providing an interface? It's because if LanguageContainer is an interface, then there would be package name conflict of languagecontainer/release package (language agostic) and release package (language-specific. In this case Java-specific). Here is a piece of code.
  • Main command dispatch refactor: The librariangen main.go has been refactored to delegate non-generate commands to the new languagecontainer.Run function, centralizing command execution and wiring up release.Init for the release-init command.

  • message.Change struct update: The SourceCommitHash field in the message.Change struct has been renamed to CommitHash for improved clarity and consistency. This is due to the recent renaming of the field and google-cloud-go/internal/librariangen/request.Change already has the field.

The user (Java's language container in this case) doesn't have to implement the parsing logic and the tests. I moved the argument parsing tests to languagecontainer/languagecontainer_test.go from main_test.go.

@product-auto-label product-auto-label bot added the size: l Pull request size is large. label Oct 21, 2025
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @suztomo, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a significant architectural change by creating a new languagecontainer package. This package is designed to provide a standardized interface and execution environment for language-specific operations within the librariangen tool. The initial implementation focuses on integrating the release-init command, allowing it to parse requests, execute language-specific logic, and write responses in a structured manner. This refactoring aims to improve modularity and prepare the librariangen tool for future expansion with other language-specific commands like generate and build.

Highlights

  • New languagecontainer package: A new languagecontainer package has been introduced to encapsulate language-specific container operations and command execution logic, promoting modularity.
  • release-init command parsing: The languagecontainer.Run function now includes robust logic to parse release-init requests from JSON files, handle command-line flags, and invoke the ReleaseInit function.
  • Main command dispatch refactor: The librariangen main.go has been refactored to delegate non-generate commands to the new languagecontainer.Run function, centralizing command execution and wiring up release.Init for the release-init command.
  • message.Change struct update: The SourceCommitHash field in the message.Change struct has been renamed to CommitHash for improved clarity and consistency.
  • Comprehensive testing: New unit tests have been added for the languagecontainer package, thoroughly covering command execution, flag parsing, and the request/response flow for release-init.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@codecov
Copy link

codecov bot commented Oct 21, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.27%. Comparing base (f22935d) to head (e0cf405).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3965      +/-   ##
==========================================
- Coverage   88.37%   80.27%   -8.11%     
==========================================
  Files           6        8       +2     
  Lines         370      441      +71     
==========================================
+ Hits          327      354      +27     
- Misses         30       68      +38     
- Partials       13       19       +6     
Flag Coverage Δ
librariangen 80.27% <ø> (-8.11%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

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

cmd := args[0]
flags := args[1:]
switch cmd {
case "generate":
Copy link
Member Author

Choose a reason for hiding this comment

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

I'll move the generate command parsing here. Once Mike's generate command work stop having conflict.

Copy link
Member

Choose a reason for hiding this comment

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

I don't have any outstanding PRs right now. I think it's OK to move it. I can deal with the merge with my WIP.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll change that in a subsequent pull request.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new languagecontainer package to abstract command execution, starting with the release-init command. The refactoring in main.go delegates command handling to this new package, which is a good step towards modularity. My feedback focuses on improving robustness by avoiding panics, adhering to structured logging best practices, enhancing test clarity, and addressing a regression in test coverage in main_test.go.

"github.com/google/go-cmp/cmp"
)

func TestRun(t *testing.T) {
Copy link
Member Author

Choose a reason for hiding this comment

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

This test is from main_test.go

"cloud.google.com/java/internal/librariangen/generate"
)

func TestRun(t *testing.T) {
Copy link
Member Author

Choose a reason for hiding this comment

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

This goes to languagecontainer_test.go.

@suztomo suztomo requested a review from meltsufin October 21, 2025 23:29
@suztomo suztomo force-pushed the release_init_signature branch from 2d0b042 to 28cb6cd Compare October 21, 2025 23:32
…request

The languagecontainer package parses the request JSON file and calls the
corresponding implementation method.
The user (Java's language container in this case) doesn't have to implement the parsing logic and the tests. I moved the argument parsing tests to languagecontainer/languagecontainer_test.go from main_test.go.
@suztomo suztomo force-pushed the release_init_signature branch from 28cb6cd to 75337ca Compare October 21, 2025 23:33
@suztomo
Copy link
Member Author

suztomo commented Oct 22, 2025

Thank you Gemini Code Assist. I added that to the PR description.

Copy link
Member

@meltsufin meltsufin left a comment

Choose a reason for hiding this comment

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

I think ideally this would be two separate PRs, one for introducing languagecontainer, and another for adding release-init command support.

case "configure":
slog.Warn("librariangen: configure command is not yet implemented")
return 1
case "release-init":
Copy link
Member

Choose a reason for hiding this comment

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

I think this is a lot code to put into a switch statement. Do you think it would make sense to move it to a separate function, like it was done for generate?

Copy link
Member Author

Choose a reason for hiding this comment

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

Let me work on that.

Copy link
Member Author

Choose a reason for hiding this comment

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

Added handleReleaseInit here.

cmd := args[0]
flags := args[1:]
switch cmd {
case "generate":
Copy link
Member

Choose a reason for hiding this comment

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

I don't have any outstanding PRs right now. I think it's OK to move it. I can deal with the merge with my WIP.

)

// LanguageContainer defines the functions for language-specific container operations.
type LanguageContainer struct {
Copy link
Member

Choose a reason for hiding this comment

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

Why not use an interface here?

Copy link
Member Author

@suztomo suztomo Oct 22, 2025

Choose a reason for hiding this comment

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

If this is an interface, then there would be package name conflict of languagecontainer/release package (language agostic) and release package (language-specific. In this case Java-specific). Here is a piece of code when I tried to introduce languagecontainer/release and release packages. The naming conflict happened and I had to rename one of them to release2:

package main

import (

... (omit)...

	"cloud.google.com/java/internal/librariangen/generate"
	release2 "cloud.google.com/java/internal/librariangen/languagecontainer/release"
	"cloud.google.com/java/internal/librariangen/message"
	"cloud.google.com/java/internal/librariangen/release"
)

... (omit)...

// javaContainer implements the LanguageContainer interface for Java.
type javaContainer struct{}

// ReleaseInit implements the LanguageContainer interface for Java.
func (c *javaContainer) ReleaseInit(ctx context.Context, cfg *release2.Config) (*message.ReleaseInitResponse, error) {
	return release.Init(ctx, cfg)
}

I just added this observation in the description of this pull requests.

CC: @codyoss We talked about interface v.s. a struct with functions. I now think the struct is better because we don't have to rename "languagecontainer/release" package when we use (language-specific) "release" package used in main.go.

@suztomo suztomo requested a review from meltsufin October 22, 2025 18:29
@suztomo
Copy link
Member Author

suztomo commented Oct 22, 2025

I think ideally this would be two separate PRs, one for introducing languagecontainer, and another for adding release-init command support.

I thought about that too, but I think it's more clear if the introduction of languagecontainer has one usage of the package. Subsequent pull requests will be more fine-grained.

}

// Run accepts an implementation of the LanguageContainer.
func Run(args []string, container LanguageContainer) int {
Copy link
Member

Choose a reason for hiding this comment

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

Should this be a pointer *LanguageContainer?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, that's a good catch. Updated to use a pointer.

cmd := args[0]
flags := args[1:]
switch cmd {
case "generate":
Copy link
Member

Choose a reason for hiding this comment

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

I would imagine you would check if the passed in LanguageContainer struct includes the corresponding functions, and if so invoke them, otherwise log the warning.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, that's the plan. In this pull requests, LanguageContainer only has ReleaseInit function.

Copy link
Member Author

Choose a reason for hiding this comment

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

Added that in #3968.

@suztomo suztomo requested a review from meltsufin October 22, 2025 19:46
@meltsufin meltsufin self-requested a review October 22, 2025 23:14
Copy link
Member

@meltsufin meltsufin left a comment

Choose a reason for hiding this comment

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

I approved it, but then I noticed the code coverage dropping by 8.11%. Can you look into this please?

@suztomo
Copy link
Member Author

suztomo commented Oct 23, 2025

@meltsufin I checked the coverage (go test -race -coverprofile=coverage.out -covermode=atomic ./... and go tool cover -html=coverage.out). These newly missed lines are from the main.go's run function. languagecontainer.Run will replace this function. This pull request moved the test cases from main_test.go to languagecontainer_test.go.

Screenshot 2025-10-22 at 8 57 36 PM

@suztomo suztomo merged commit a26a6d9 into main Oct 23, 2025
59 of 60 checks passed
@suztomo suztomo deleted the release_init_signature branch October 23, 2025 14:15
@suztomo
Copy link
Member Author

suztomo commented Oct 23, 2025

I temporarily removed "build (11)", "build (17)", and "showcase (25)".

@suztomo
Copy link
Member Author

suztomo commented Oct 23, 2025

I don't have any outstanding PRs right now. I think it's OK to move it. I can deal with the merge with my WIP.

@meltsufin Created #3968.

meltsufin added a commit that referenced this pull request Oct 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size: l Pull request size is large.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants