Skip to content

Comments

Commands generator binary#875

Merged
stephanos merged 8 commits intotemporalio:mainfrom
stephanos:reusable-codegen
Dec 2, 2025
Merged

Commands generator binary#875
stephanos merged 8 commits intotemporalio:mainfrom
stephanos:reusable-codegen

Conversation

@stephanos
Copy link
Contributor

@stephanos stephanos commented Nov 18, 2025

What was changed

Make gen-commands and gen-docs a binary that can be used any YAML input.

Why?

Temporal wants to re-use the commandsgen tool for other internal CLIs.

It is not supported for users outside of Temporal.

Checklist

  1. Closes

  2. How was this tested:

  1. Any docs updates needed?

@stephanos stephanos changed the title Reusable command generator Reusable commands generator Nov 18, 2025
@stephanos stephanos force-pushed the reusable-codegen branch 6 times, most recently from a62ab07 to 7a4a80c Compare November 18, 2025 23:15
[
ubuntu-latest,
macos-latest,
macos-15-intel,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Image

@stephanos stephanos marked this pull request as ready for review November 19, 2025 00:20
@stephanos stephanos requested review from a team as code owners November 19, 2025 00:20
@stephanos stephanos requested a review from cretz November 19, 2025 00:20
"sort"
"strings"

"go.temporal.io/server/common/primitives/timestamp"
Copy link
Contributor Author

@stephanos stephanos Nov 19, 2025

Choose a reason for hiding this comment

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

Copied parseDuration to remove server dependency here.

@stephanos stephanos marked this pull request as draft November 19, 2025 19:59
@stephanos stephanos force-pushed the reusable-codegen branch 8 times, most recently from 37c08bb to 4423bb2 Compare November 27, 2025 00:16
s.NoError(res.Err)
out := res.Stdout.String()
var out string
s.EventuallyWithT(func(t *assert.CollectT) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Was flaky.

assert.Contains(t, res.Stdout.String(), deploymentName1)
assert.Contains(t, res.Stdout.String(), version1.BuildID)
assert.Contains(t, res.Stdout.String(), deploymentName2)
assert.Contains(t, res.Stdout.String(), version2.BuildID)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Was flaky.

if: ${{ matrix.checkGenCommands }}
run: |
go run ./internal/cmd/gen-commands
go run ./cmd/gen-commands -pkg temporalcli -context "*CommandContext" < internal/temporalcli/commands.yaml > internal/temporalcli/commands.gen.go
Copy link
Contributor Author

@stephanos stephanos Nov 27, 2025

Choose a reason for hiding this comment

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

This is where I would invoke make gen but received strong objections last time.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, IMO we should avoid adding platform dependent code. Any contributor on any supported platform should be able to basically run the same commands as our CI does

Comment on lines 66 to 70
- name: Generate docs, confirm working
if: ${{ matrix.checkGenCommands }}
run: |
go run ./cmd/gen-docs -output dist/docs < internal/temporalcli/commands.yaml

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Better to know immediately if this is broken.

@stephanos stephanos changed the title Reusable commands generator Commands generator binary Nov 29, 2025
buf bytes.Buffer
allCommands []Command
OptionSets []OptionSets
contextType string
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Allow custom context name.

return &s
}

var reDays = regexp.MustCompile(`(\d+(\.\d*)?|(\.\d+))d`)
Copy link
Contributor Author

@stephanos stephanos Nov 29, 2025

Choose a reason for hiding this comment

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

As this is generated code, I think it's fine for the var and type to not be at the top here to keep the codegen simple. Similarly, a single generated file seems easier do manage and generate then multiple.


// appendGoSource parses a Go source file, registers its imports, and appends
// everything after the import block to the output buffer.
func (c *codeWriter) appendGoSource(src string) error {
Copy link
Contributor Author

@stephanos stephanos Nov 29, 2025

Choose a reason for hiding this comment

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

It was either this, string literals or regex; this seems like the best approach to me.

@stephanos stephanos marked this pull request as ready for review November 29, 2025 17:39
if: ${{ matrix.checkGenCommands }}
run: |
go run ./internal/cmd/gen-commands
go run ./cmd/gen-commands -pkg temporalcli -context "*CommandContext" < internal/temporalcli/commands.yaml > internal/temporalcli/commands.gen.go
Copy link
Member

Choose a reason for hiding this comment

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

Yes, IMO we should avoid adding platform dependent code. Any contributor on any supported platform should be able to basically run the same commands as our CI does

Copy link
Member

@cretz cretz Dec 1, 2025

Choose a reason for hiding this comment

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

I think this and the other could also be considered a "hidden" internal sub-command of the existing CLI (probably manually added, not via existing yaml file, which allows it to be easily versioned/downloaded and doesn't require these top-level dirs. The bootstrapping problem is very slight.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's fair; since it is an internal tool only. 👍

Copy link
Member

Choose a reason for hiding this comment

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

I was saying they could be just commands on the existing binary (but hidden from "help"). Technically a completely different binary is fine too, but you lose the ability to easily download/version this binary.

Copy link
Contributor Author

@stephanos stephanos Dec 2, 2025

Choose a reason for hiding this comment

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

Oh, sorry, I misread. I have mixed feelings about including it directly in the Temporal CLI; it feels like it shouldn't be including the dev tooling itself.

AFAICS go run github.com/temporalio/cli/internal/cmd/gen-commands@<version> is how you'd run the command generator. And it would respond to the same git tags as the Temporal CLI as it's in the same repo.

Or should we consider moving it to a separate repo; now that we a standalone binary?

Copy link
Member

Choose a reason for hiding this comment

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

I'm ok w/ how you have it now, just a thought of making it a separate command gets all of the packaging/deployment benefits, but what you have here is fine

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 we can always make adjustments later once we some learnings.

flag.Parse()

// Read input from stdin
yamlBytes, err := io.ReadAll(os.Stdin)
Copy link
Member

Choose a reason for hiding this comment

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

Personal preference is to (also?) accept files for both directions, but it's not a big deal for an internal tool

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 I'll change it to a file input, no strong opinions on my end

CONTRIBUTING.md Outdated
[commands.gen.go](internal/temporalcli/commands.gen.go) file from code, simply run:

go run ./internal/cmd/gen-commands
make gen
Copy link
Member

Choose a reason for hiding this comment

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

We support contributors on all of our supported platforms and therefore contributing guide should work across all platforms we support IMO

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Consider this a Freudian slip. Fixed.

@stephanos stephanos requested a review from cretz December 2, 2025 16:53
Copy link
Member

@cretz cretz left a comment

Choose a reason for hiding this comment

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

LGTM, only two minor concerns

Copy link
Member

Choose a reason for hiding this comment

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

I was saying they could be just commands on the existing binary (but hidden from "help"). Technically a completely different binary is fine too, but you lose the ability to easily download/version this binary.

gen-commands Outdated
Copy link
Member

Choose a reason for hiding this comment

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

Were these committed intentionally?

@stephanos stephanos merged commit 19449ab into temporalio:main Dec 2, 2025
8 checks passed
@stephanos stephanos deleted the reusable-codegen branch December 2, 2025 19:15
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.

2 participants