Skip to content
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

Cannot depend on generated client #22

Open
AndrewGuenther opened this issue May 21, 2021 · 16 comments
Open

Cannot depend on generated client #22

AndrewGuenther opened this issue May 21, 2021 · 16 comments

Comments

@AndrewGuenther
Copy link

AndrewGuenther commented May 21, 2021

Hopefully I'm missing something simple, but so far as I can tell, when using openapi_generator it doesn't appear to declare and outputs. So in my use case, I am generating a Python client which will then be depended on by a py_library. This doesn't appear to work.

I'd appreciate if someone could provide an example where they depend on a generated client and how that gets wired up. Thanks!

Some additional context on what I've tried:

openapi_generator(
    name = "my_api_client_src",
    generator = "python",
    spec = ":my_api_spec.yaml",
    deps = [
        ":my_api_spec"
    ],
    visibility = ["//visibility:public"]
)

py_library(
    name = "my_library",
    deps = [":my_api_client_src"]
)

The above will claim that the my_api_client_src target doesn't contain any python files, so I've tried depending on it as data instead and making a dedicated py_library target for it, but that doesn't appear to work either.

@rajukrishnamurthy
Copy link

This seems to be similar to issue #6 I think it has something to do the implementation returning all the files:

    return DefaultInfo(files = depset([
        declared_dir,
    ]))

@juhwan-jeong-hub
Copy link

Any updates on this? I'm trying to use go_library

openapi_generator(
    name="sample-go-src",
    generator="go",
    spec="sample.yaml",
    api_package = "com.swagger.api",
    model_package = "com.swagger.model",
)

go_library(
  name = "sample-go",
#  srcs = glob(["**/*.go"]),
#  deps = [":sample-go-src"],
  srcs = [":sample-go-src"],
  importpath = <omitted>,
)

Building sample-go fails with Error in fail: Unknown source type sample-go-src

@ashwin153
Copy link

ashwin153 commented Mar 31, 2022

I can't depend on the generated code either in typescript. @wing328 Can you post an example of how to depend on the outputs of this?

@N1v0k
Copy link

N1v0k commented Apr 20, 2022

Hi,

I tried to solve this issue but unfortunately I couldn't find a way around a major obstacle.

The generator-cli's output is not transparent, which is the reason why the output files can't be defined in advance, which is required for bazel.

In other words, I couldn't find a way to define the output files based on the yaml, since the way bazel is built, you would have to parse the yaml in advance and additionally know the implementation of the generator-cli, which defines the naming convention (eg. InlineResponse500.ts)

The workaround for me is to just generate the client manually and compiling the resulting typescript files as usual with bazel. (Which is not a solution one is looking for in this repo)

I don't really see any benefit in using this "bazel" tool. Which is a pity if you try to use open-api in a bigger project, where you need to automate these steps.

@rajukrishnamurthy
Copy link

I think the only way to do this is have this be a appropriate provider and create a switch statement for every language to filter for the "library" files. I was going to write something specific for the few languages that we needed support for, but we went a completely different route.

@ahumesky
Copy link

Hi, this question was raised on stackoverflow, and some workarounds, at least for python, are discussed there:
https://stackoverflow.com/a/73411230/6327445

@ahumesky
Copy link

ahumesky commented Aug 19, 2022

Also, the java rules can take a source jar in srcs, so one workaround for the generated java code is to zip up the java files from the generated directory. Something like this:

WORKSPACE:

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
    name = "openapi_tools_generator_bazel",
    sha256 = "c6e4c253f1ae0fbe4d4ded8a719f6647273141d0dc3c0cd8bb074aa7fc3c8d1c",
    urls = ["https://github.com/OpenAPITools/openapi-generator-bazel/releases/download/0.1.5/openapi-tools-generator-bazel-0.1.5.tar.gz"],
)

load("@openapi_tools_generator_bazel//:defs.bzl", "openapi_tools_generator_bazel_repositories")

# You can provide any version of the CLI that has been uploaded to Maven
openapi_tools_generator_bazel_repositories(
    openapi_generator_cli_version = "5.1.0",
    sha256 = "62f9842f0fcd91e4afeafc33f19a7af41f2927c7472c601310cedfc72ff1bb19"
)

RULES_JVM_EXTERNAL_TAG = "4.2"
RULES_JVM_EXTERNAL_SHA = "cd1a77b7b02e8e008439ca76fd34f5b07aecb8c752961f9640dea15e9e5ba1ca"
http_archive(
    name = "rules_jvm_external",
    strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG,
    sha256 = RULES_JVM_EXTERNAL_SHA,
    url = "https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip" % RULES_JVM_EXTERNAL_TAG,
)
load("@rules_jvm_external//:repositories.bzl", "rules_jvm_external_deps")
rules_jvm_external_deps()
load("@rules_jvm_external//:setup.bzl", "rules_jvm_external_setup")
rules_jvm_external_setup()
load("@rules_jvm_external//:defs.bzl", "maven_install")

maven_install(
    artifacts = [
        "io.swagger:swagger-annotations:1.5.24",
        "com.google.code.findbugs:jsr305:3.0.2",
        "com.squareup.okhttp3:okhttp:3.14.7",
        "com.squareup.okhttp3:logging-interceptor:3.14.7",
        "com.google.code.gson:gson:2.8.6",
        "io.gsonfire:gson-fire:1.8.4",
        "org.apache.commons:commons-lang3:3.10",
        "org.threeten:threetenbp:1.4.3",
        "javax.annotation:javax.annotation-api:1.3.2",
    ],
    repositories = [
        "https://repo1.maven.org/maven2",
    ],
)

BUILD:

load("@openapi_tools_generator_bazel//:defs.bzl", "openapi_generator")

openapi_generator(
  name = "gen_petstore_java",
  generator = "java",
  spec = "petstore.yaml",
)

genrule(
  name = "get_petstore_java_srcs",
  srcs = [":gen_petstore_java"],
  outs = ["petstore.srcjar"],
  exec_tools = ["@bazel_tools//tools/zip:zipper"],
  cmd = """
files=$$(find -L $(location :gen_petstore_java)/src/main/java -type f)
zipper_args=()
for f in $${files[@]}; do
  path_in_zip="$${f/bazel-out\\/k8-fastbuild\\/bin\\/gen_petstore_java\\/src\\/main\\/java\\//}"
  zipper_args+=("$$path_in_zip=$$f")
done
$(location @bazel_tools//tools/zip:zipper) c $@ $${zipper_args[@]}
""", 
)

java_library(
  name = "petstore_java",
  srcs = [":petstore.srcjar"],
  deps = [
    "@maven//:io_swagger_swagger_annotations",
    "@maven//:com_google_code_findbugs_jsr305",
    "@maven//:com_squareup_okhttp3_okhttp",
    "@maven//:com_squareup_okhttp3_logging_interceptor",
    "@maven//:com_google_code_gson_gson",
    "@maven//:io_gsonfire_gson_fire",
    "@maven//:org_apache_commons_commons_lang3",
    "@maven//:org_threeten_threetenbp",
    "@maven//:javax_annotation_javax_annotation_api",
  ],
)

java_binary(
  name = "petstore_java_main",
  srcs = ["java/petstore/Main.java"],
  deps = [":petstore_java"],
  main_class = "petstore.Main",
)

The maven deps I got from the generated build.gradle file, but I got compilation errors like this

org/openapitools/client/ApiClient.java:818: error: no suitable method found for create(byte[],MediaType)

so something's not lined up between the generated code and the deps, but the main idea is the get_petstore_java_srcs genrule.

@loeffel-io
Copy link

+1

@loeffel-io
Copy link

loeffel-io commented Dec 3, 2022

this makes it "impossible" to work with in a multi language repository

@PertsevRoman
Copy link
Contributor

Hi guys,
I implemented a simple workaround. Bazel requires to know exact list of input and output files. Also Bazel does not offer anything that could be useful during an analysis (parse swagger/openapi YAML, etc.). So I forked the repo and specified additional attributes which takes generated models list. Now generation works well and I'm able to import models/invokers to java_library target and so on.
There is possible solution from my perspective: add something like gazelle functionality and generate bazel code manually but using a convenient tool. WDYT ?

@lionelfleury
Copy link
Contributor

lionelfleury commented May 9, 2023

Hi all,
A simple Golang example - keeping only relevant *.go files:

load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
load("@openapi_tools_generator_bazel//:defs.bzl", "openapi_generator")
load("@aspect_bazel_lib//lib:copy_to_directory.bzl", "copy_to_directory")

openapi_generator(
    name = "petstore",
    generator = "go-gin-server",
    spec = "petstore.yml",
)

copy_to_directory(
    name = "petstore.go",
    srcs = [":petstore"],
    exclude_srcs_patterns = ["**/main.go"],
    include_srcs_patterns = ["**/*.go"],
)

go_library(
    name = "server_lib",
    srcs = [":petstore.go"],
    importpath = "petstore",
    visibility = ["//visibility:private"],
    deps = ["@com_github_gin_gonic_gin//:go_default_library"],
)

go_binary(
    name = "server",
    srcs = ["main.go"],
    visibility = ["//visibility:public"],
    deps = [":server_lib"],
)

The trick is the petstore.go folder name to fool rules_go that this is valid input.

NOTE: you need your own main.go file:

package main

import (
	"log"
	sw "petstore"
)

func main() {
	log.Printf("Server started")
	router := sw.NewRouter()
	log.Fatal(router.Run(":8080"))
}

Inspired from C++ example here: https://stackoverflow.com/questions/48417712/how-to-build-static-library-from-the-generated-source-files-using-bazel-build

@guillaumep
Copy link

Using copy_to_directory and including the result as data instead of srcs seems to have worked for us:

openapi_generator(
    name = "xcover_client_codegen",
    additional_properties = {
        "packageName": "xcover_python_client",
    },
    generator = "python",
    spec = "swagger.json",
)

copy_to_directory(
    name = "xcover_python_client",
    srcs = [":xcover_client_codegen"],
    include_srcs_patterns = ["xcover_client_codegen/xcover_python_client/**"],
    replace_prefixes = {
        "xcover_client_codegen/xcover_python_client": "",
    },
)

py_library(
    name = "xcover_python_client_lib",
    # Output from openapi_generator is a directory and not a list of files, so we
    # include it as data instead of as srcs, in order to prevent Bazel from emitting
    # a warning that no .py files were found.
    data = [
        ":xcover_python_client",
    ],
    imports = ["."],
    visibility = ["//visibility:public"],
    deps = [
        requirement("python_dateutil"),
        requirement("urllib3"),
    ],
)

But really the OpenAPI generator rules should probably be rewritten as repository rules... (https://bazel.build/extending/repo)

@fjij
Copy link

fjij commented Nov 23, 2023

Here's a solution to the problem that doesn't use copy_to_directory. It's similar to @guillaumep's solution, but uses the imports attribute of py_library.

openapi_generator(
    name = "my_client",
    additional_properties = {
        "packageName": "my_client",
    },
    generator = "python",
    spec = "swagger.json",
)

py_library(
    name = "my_client_py",
    data = [":my_client"],
    imports = ["./my_client"],
    visibility = ["//visibility:public"],
    deps = [
        requirement("python_dateutil"),
        requirement("urllib3"),
    ],
)

@hnoshab75
Copy link

hnoshab75 commented Jan 8, 2024

I have seen some issues while running the go-gin-server generator, has anyone been able to use the go-server generator for go successfully?

If we try to use the copy_to_directory(), the go_library() panics with unused dep statements.

@darkrift
Copy link

darkrift commented Feb 2, 2024

I have seen some issues while running the go-gin-server generator, has anyone been able to use the go-server generator for go successfully?

If we try to use the copy_to_directory(), the go_library() panics with unused dep statements.

This would be a bug in the code generation and should be fixed as part of the main project. I am able to generate code with the go-server generator in my project.

Make sure you also use the latest version of the cli.

@loeffel-io
Copy link

loeffel-io commented Mar 19, 2024

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

No branches or pull requests