Search code examples
gogo-swagger

Go-Swagger: Is it possible to generate a Swagger spec for multiple workspaces together?


I am following the instruction from https://swagger.io/specification/ to generate a Swagger spec from my code. My project is comprised of several services, and I have a root folder which has a couple of workspaces in it (I have a workspace for each service). Inside the root folder there is only a go.work file, specifying the path to each workspace. The structure of my project is as follows:

myworkspaceRoot/
├── go.work
├── go.work.sum
├── Subfolder
     ├──── workspace1/
     │      ├── go.mod
     │      └── ...
     ├──── workspace2/
     │      ├── go.mod
     │      └── ...
     └──── workspace3/
            ├── go.mod
            └── ...

Each workspace is a unique service with its own main file and dependencies. I managed to generate the Swagger spec files for each workspace individually, but I want to generate a new spec file which contains the documentation for all of the system. Is it possible to do this with my current settings? Since Go-Swagger starts from a file and scans every path (If I am not mistaken) my first idea was to create a main file in the root folder and import all of the packages, but this was of course futile as I was given the error that main was redeclared in the package(which I think can be solved by separating each directory but that does not suit my project).

Consequently, If I just run the swagger generate spec -o swagger.yml --scan-models command on the root folder without anything extra, it generates an empty swagger.yml file as expected.

The second option is always to write a script which combines all of the generated specs for individual services, but I was looking for a more intuitive answer, if one exists.


Solution

  • So my Initial Idea was correct, but the implementation not so much, and that was the cause for my failure. Basically, the plan is to create a Go file in the root folder which acts as a meta service; Importing the path of all of the packages that we want to document so that Swagger has access to them, and start generating the specs from that file. The reason that it failed the first time was that all of the packages that I wanted to import were main packages, making them executables rather than importable libraries.

    In Go, main is actually a special package name which indicates that the package contains the code for an executable application. That is, it indicates that the package contains code that can be built into a binary and run.

    For more information, read this blog. So what I did was to change the name of the packages of the workspaces from main, which in turn changed the type of the packages. Take Caution that I was not working on a real project, and hence, I did not bother myself with the consequences of suddenly changing the name and type of a package. In a real project, one should exercise more care when doing this, and if changing the type of the package is not possible, find better solution(E.g. one Idea maybe to transfer the required methods in another Go package of library type, or writing a script to combine the Swagger specs). All in all, this is how my meta.go looks like:

    package main
    
    import (
        "fmt"
    
        _ "example.com/workspace1"
        _ "example.com/workspace2"
        _  etc.
    
    )
    
    func doc() {
        fmt.Println("Meta service online")
    }
    

    And If I wanted to add a go.mod file with this file it would look something like this:

    module example.com/Meta
    
    go 1.22.2
    
    replace example.com/Workspace1 => ./Subfolder/workspace1
    
    require example.com/Workspace1 v0.0.0