DEV Community

MacLikorne
MacLikorne

Posted on

A preview environment in less than 5 minutes for Gin (Go) and Postgresql

Introduction

One does not simply deploy a production environment and a developing one on its favorite Cloud Provider (AWS, Scaleway, Digital Ocean).

When it comes to testing new features or improvements, few options come to you. You do some unit tests but you’re not 100% sure everything works together. So you switch to integration tests but now you can’t be sure all your services will still work together. Then you set up an end-to-end testing pipeline but where do you run it ? On your developing branch once you merge your changes ? And what ? You rollback to a previous commit if it fails ? It’s time consuming and can introduce issues if someone rebases your flaky code.

And what if I tell you that there is a way to run your end-to-end tests on a dedicated environment deployed in less than 5 minutes ?

Qovery offers a way to do it blazingly fast. This platform does not only allow you to deploy your infrastructure and applications on your cloud account but also some great features to improve your production and preview environments is one of them.

Demo

  1. Create a service with Gin
    For this demo, I’ll create a little service that will allow me to store numbers in a database thru an API.

    func AddNumber(context *gin.Context, db *pg.DB) {
    value, parseErr := strconv.ParseInt(context.Param("number"), 10, 64)
    if parseErr != nil {
        context.String(http.StatusBadRequest, "%s", parseErr.Error())
        return
    }
    
    _, insertErr := db.Model(&Number{Value: value}).Insert()
    if insertErr != nil {
        context.String(http.StatusInternalServerError, "Cannot store %d: %s", value, insertErr.Error())
        return
    }
    
    context.String(http.StatusOK, "%d stored.", value)
    }
    
  2. Deploy the app with Qovery
    There are two ways to handle the build phase with Qovery, Buildpacks, which will identify the programming language and generate an image, or Docker with a Dockerfile. I’ll use the second one since I’m used to it and it gives me more control.

    FROM golang:1.17.1-buster as build
    
    ADD ./cmd /src/cmd
    ADD ./pkg /src/pkg
    ADD ./go.mod /src
    WORKDIR /src/cmd
    RUN go get && go build -o /gin_test.bin main.go
    
    FROM debian:buster-slim as run
    
    RUN apt-get update && apt-get install -y ca-certificates 
    && apt-get clean
    COPY --from=build /gin_test.bin /usr/bin/gin_test
    CMD ["/usr/bin/gin_test"]
    
  3. Setup your environment on Qovery
    Assuming I already have an infra running, I’ll just create "gin_test" project.

    create_project

    Then a “production” environment.

    create_env

    And to finish, my application.

    create_app_1

    create_app_2

    Then I enable the “Preview Environment” option.

    enable_preview

    If I take a look at auto generated environment variables, Qovery offers me all I need to connect to Postgresql.

    env_vars

    Let’s put it in my code.

    func ConnectToDatabase() *pg.DB {
    addr := fmt.Sprintf("%s:%s",
        GetEnvironmentVariable("POSTGRESQL_HOST"),
        GetEnvironmentVariable("POSTGRESQL_PORT"),
    )
    options := &pg.Options{
        User:     GetEnvironmentVariable("POSTGRESQL_LOGIN"),
        Password: GetEnvironmentVariable("POSTGRESQL_PASSWORD"),
        Addr:     addr,
        Database: GetEnvironmentVariable("POSTGRESQL_DEFAULT_DATABASE_NAME"),
    }
    
    db := pg.Connect(options)
    if db == nil {
        log.Fatal("Failed to connect to database. Closing app.")
    }
    
    log.Print("Connected to database.")
    
    return db
    }
    

    And deploy it all !

    deployment

    And let’s see if it works.

    add_curl_1

    Amazing !!!

  4. Add a feature and open a pull request
    Well, now I can store numbers but I’d like to get the list of stored ones when reaching another endpoint.

    func ListNumbers(context *gin.Context, db *pg.DB) {
    var numbers []Number
    listErr := db.Model(&numbers).Select()
    if listErr != nil {
        context.String(http.StatusInternalServerError, "Cannot list numbers: %s", listErr.Error())
        return
    }
    
    context.String(http.StatusOK, "Numbers list: %v", numbers)
    }
    

    My service is ready to test, let’s open a pull request.

    pull_request

  5. Check your preview environment
    And now, if we take a look at Qovery console, we have a new environment named with me pull request.

    multiple_envs

    And I also already have a fresh new URL related to my preview environment.

    Let's add some numbers since in my preview environment it's a fresh new database with dedicated endpoint.

    add_curl_2

    I now want to see if my new awesome list feature works.

    list_curl

    I’m now able to run manual tests or end-to-end tests on this endpoint.

  6. Merge it all
    Since everything looks to work perfectly, let’s merge this !

    merge

    We can notice the preview environment is deleting and the production one is redeploying Qovery side.

    ui_merge

    And now I can list previously stored numbers.

    list_curl_2

Conclusion

In this article, we quickly see how to set up a backend service written in Go with Gin linked to a Postgresql database. We enabled the Preview Environment feature to develop new features more quickly. And BOOM ! Opened a pull request so I can test my feature !

Git repository : https://github.com/MacLikorne/gin_test

Top comments (0)