From e68bbd9dfc457db9393088e75a8d5bc0d29b5ae6 Mon Sep 17 00:00:00 2001 From: Mladen Jablanovic Date: Wed, 24 Jun 2026 16:06:10 +0200 Subject: [PATCH 1/3] fix(cli): detect file upload params by type, and run CLI build on PRs The CLI handlebars template detected binary upload params by matching the literal param name (file/filename). A required binary field named anything else fell through to the primitive handler and emitted invalid Go (params.Get*os.File), breaking the CLI build. The screenshot/create endpoint, whose binary field is named "filename" and is required, hit exactly this case. Switch both the required and optional branches to {{#isFile}}, the flag the generator derives from `format: binary` and that the go/python/typescript/php templates here already use. File uploads are now detected by type, not name. This break reached main because no CI job compiled the CLI on the PR: - test-cli.yml (the only job that runs `go build` on the CLI) filtered on paths that exclude the spec and CLI templates the CLI is generated from, so a spec-only change skipped it. Switch it to pull_request and expand the path filter to cover paths/, schemas/, the shared *.yaml, and the CLI templates. - build.yml's build-cli job published the generated CLI to phrase-cli without ever compiling it. Add a `go build` (against the freshly generated go client) before publishing so non-compiling code can't ship. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/build.yml | 5 +++++ .github/workflows/test-cli.yml | 11 +++++++++-- openapi-generator/templates/cli/api.handlebars | 8 ++++---- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ac6ca0764..3e57d4ba4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -59,7 +59,12 @@ jobs: GOPRIVATE: github.com/phrase/phrase-go run: | npm install + npm run generate.go npm run generate.cli + # Verify the generated CLI compiles before publishing it. Build against + # the freshly generated go client so this does not depend on a released + # phrase-go version that may lag behind the spec. + (cd ./clients/cli && go mod edit -replace github.com/phrase/phrase-go/v4=../go && go build . && go mod edit -dropreplace github.com/phrase/phrase-go/v4) git clone https://$API_TOKEN_GITHUB@github.com/phrase/phrase-cli.git clones/cli &> /dev/null rsync -avI --delete --exclude='.git/' clients/cli/ clones/cli cd clones/cli diff --git a/.github/workflows/test-cli.yml b/.github/workflows/test-cli.yml index 44422f927..91aa9294f 100644 --- a/.github/workflows/test-cli.yml +++ b/.github/workflows/test-cli.yml @@ -2,11 +2,18 @@ # Once we add tests, we should add a step here to run them name: Run CLI Tests on: - push: + pull_request: paths: - - .github/workflows/test-cli.yml + - 'paths/**' + - 'schemas/**' + - 'parameters.yaml' + - 'responses.yaml' + - 'headers.yaml' + - 'main.yaml' + - 'openapi-generator/templates/cli/**' - openapi-generator/cli_lang.yaml - 'clients/cli/**' + - .github/workflows/test-cli.yml jobs: test: runs-on: ubuntu-latest diff --git a/openapi-generator/templates/cli/api.handlebars b/openapi-generator/templates/cli/api.handlebars index 18e1c3c0c..9acf844a0 100644 --- a/openapi-generator/templates/cli/api.handlebars +++ b/openapi-generator/templates/cli/api.handlebars @@ -54,14 +54,14 @@ func init{{{nickname}}}() { {{#allParams~}} {{#required~}} {{#isPrimitiveType~}} - {{#if (eq paramName "file")~}} + {{#isFile~}} {{paramName}}, err := os.Open(params.GetString(helpers.ToSnakeCase("{{paramName}}"))) if err != nil { HandleError(err) } {{else~}} {{paramName}} := params.Get{{{capitalizeFirst dataType}}}(helpers.ToSnakeCase("{{{vendorExtensions.x-export-param-name}}}")) - {{/if}} + {{/isFile}} {{else~}} var {{paramName}} api.{{{dataType}}} if err := json.Unmarshal([]byte(params.GetString("data")), &{{paramName}}); err != nil { @@ -72,7 +72,7 @@ func init{{{nickname}}}() { } {{/isPrimitiveType~}} {{else~}} - {{#if (or (eq paramName "file") (eq paramName "filename"))~}} + {{#isFile~}} if params.IsSet(helpers.ToSnakeCase("{{paramName}}")) { file, err := os.Open(params.GetString(helpers.ToSnakeCase("{{paramName}}"))) localVarOptionals.{{{vendorExtensions.x-export-param-name}}} = optional.NewInterface(file) @@ -111,7 +111,7 @@ func init{{{nickname}}}() { localVarOptionals.{{{vendorExtensions.x-export-param-name}}} = {{#if (eq dataType "[]string")}}{{paramName}}{{else}}optional.NewInterface({{paramName}}){{/if}} } {{/isModel}}{{/isPrimitiveType}} - {{/if}} + {{/isFile}} {{/required~}} {{/allParams~}} From a632435319cc90efb580e957167b5750d4fd15e3 Mon Sep 17 00:00:00 2001 From: Mladen Jablanovic Date: Wed, 24 Jun 2026 17:03:31 +0200 Subject: [PATCH 2/3] fix(cli): read file params using the same key flags are registered with The file-upload branches read the value via ToSnakeCase(paramName) while flags are registered via ToSnakeCase(x-export-param-name) (the AddFlag call). These are identical for names like file/filename, but diverge when the generator escapes a reserved word or disambiguates a name, in which case viper never sees the flag value for the upload. Use x-export-param-name for the lookup, matching registration and every other primitive param. Co-Authored-By: Claude Opus 4.8 (1M context) --- openapi-generator/templates/cli/api.handlebars | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openapi-generator/templates/cli/api.handlebars b/openapi-generator/templates/cli/api.handlebars index 9acf844a0..4865de418 100644 --- a/openapi-generator/templates/cli/api.handlebars +++ b/openapi-generator/templates/cli/api.handlebars @@ -55,7 +55,7 @@ func init{{{nickname}}}() { {{#required~}} {{#isPrimitiveType~}} {{#isFile~}} - {{paramName}}, err := os.Open(params.GetString(helpers.ToSnakeCase("{{paramName}}"))) + {{paramName}}, err := os.Open(params.GetString(helpers.ToSnakeCase("{{{vendorExtensions.x-export-param-name}}}"))) if err != nil { HandleError(err) } @@ -73,8 +73,8 @@ func init{{{nickname}}}() { {{/isPrimitiveType~}} {{else~}} {{#isFile~}} - if params.IsSet(helpers.ToSnakeCase("{{paramName}}")) { - file, err := os.Open(params.GetString(helpers.ToSnakeCase("{{paramName}}"))) + if params.IsSet(helpers.ToSnakeCase("{{{vendorExtensions.x-export-param-name}}}")) { + file, err := os.Open(params.GetString(helpers.ToSnakeCase("{{{vendorExtensions.x-export-param-name}}}"))) localVarOptionals.{{{vendorExtensions.x-export-param-name}}} = optional.NewInterface(file) if err != nil { HandleError(err) From 06edf3bf18750d7a46e47922769321ae3a0b08ba Mon Sep 17 00:00:00 2001 From: jablan Date: Wed, 24 Jun 2026 17:04:37 +0200 Subject: [PATCH 3/3] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .github/workflows/test-cli.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test-cli.yml b/.github/workflows/test-cli.yml index 91aa9294f..88ef6f393 100644 --- a/.github/workflows/test-cli.yml +++ b/.github/workflows/test-cli.yml @@ -5,7 +5,9 @@ on: pull_request: paths: - 'paths/**' + - 'paths.yaml' - 'schemas/**' + - 'schemas.yaml' - 'parameters.yaml' - 'responses.yaml' - 'headers.yaml'