{"id":4615,"date":"2018-02-13T08:35:07","date_gmt":"2018-02-13T16:35:07","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=4615"},"modified":"2025-06-13T22:49:05","modified_gmt":"2025-06-14T05:49:05","slug":"continuously-deploying-golang-application-using-travis-ci","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/pt\/continuously-deploying-golang-application-using-travis-ci\/","title":{"rendered":"Implanta\u00e7\u00e3o cont\u00ednua de um aplicativo Golang usando o Travis CI"},"content":{"rendered":"<p>Ent\u00e3o, voc\u00ea est\u00e1 desenvolvendo um aplicativo usando a linguagem de programa\u00e7\u00e3o Go com uma equipe de desenvolvedores para a sua organiza\u00e7\u00e3o. As pr\u00e1ticas recomendadas diriam que voc\u00ea precisa criar testes adequados e desenvolver uma estrat\u00e9gia de integra\u00e7\u00e3o e implanta\u00e7\u00e3o cont\u00ednuas.<\/p>\n<p>Se voc\u00ea estiver acompanhando meus tutoriais, lembrar\u00e1 que escrevi sobre como criar um <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/create-continuous-deployment-pipeline-nodejs-jenkins\/\" target=\"_blank\" rel=\"noopener\">pipeline de implanta\u00e7\u00e3o cont\u00ednua com Node.js e Jenkins<\/a>. Desta vez, vamos mudar as coisas com a tecnologia de desenvolvimento e o servi\u00e7o de CI\/CD.<\/p>\n<p>Veremos como implantar continuamente um aplicativo Golang que interage com <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/\" target=\"_blank\" rel=\"noopener\">Couchbase<\/a> com o popular <a href=\"https:\/\/travis-ci.org\" target=\"_blank\" rel=\"noopener\">Travis CI<\/a> servi\u00e7o.<\/p>\n<p><!--more--><\/p>\n<p>O objetivo deste tutorial \u00e9 ajud\u00e1-lo a criar um aplicativo Golang que se comunica com o Couchbase. Esse aplicativo ter\u00e1 testes de unidade adequados que ser\u00e3o usados quando o Travis CI for acionado. Se os testes forem bem-sucedidos no Travis CI, o aplicativo ser\u00e1 implantado automaticamente em algum servidor remoto com SSH.<\/p>\n<p>Como pr\u00e9-requisito, voc\u00ea precisar\u00e1 ter pelo menos uma inst\u00e2ncia do Couchbase Server dispon\u00edvel. Essa inst\u00e2ncia do Couchbase Server ser\u00e1 usada durante a implementa\u00e7\u00e3o.<\/p>\n<h2>Desenvolvimento de um aplicativo com Go e Couchbase NoSQL<\/h2>\n<p>Criaremos um novo projeto Golang para este exemplo. Em algum lugar em sua pasta\u00a0<strong>$GOPATH<\/strong> criar um arquivo chamado\u00a0<strong>main.go<\/strong> e incluem o seguinte:<\/p>\n<pre class=\"lang:default decode:true\">package main\r\n\r\nimport (\r\n\t\"fmt\"\r\n\t\"os\"\r\n\r\n\tgocb \"gopkg.in\/couchbase\/gocb.v1\"\r\n)\r\n\r\ntype Person struct {\r\n\tType      string `json:\"type\"`\r\n\tFirstname string `json:\"firstname\"`\r\n\tLastname  string `json:\"lastname\"`\r\n}\r\n\r\nvar bucket *gocb.Bucket\r\n\r\nfunc GetPersonDocument(key string) (interface{}, error) {\r\n\tvar data interface{}\r\n\t_, err := bucket.Get(key, &amp;data)\r\n\tif err != nil {\r\n\t\treturn nil, err\r\n\t}\r\n\treturn data, nil\r\n}\r\n\r\nfunc CreatePersonDocument(key string, data interface{}) (interface{}, error) {\r\n\t_, err := bucket.Insert(key, data, 0)\r\n\tif err != nil {\r\n\t\treturn nil, err\r\n\t}\r\n\treturn data, nil\r\n}\r\n\r\nfunc main() {\r\n\tfmt.Println(\"Starting the application...\")\r\n\tcluster, _ := gocb.Connect(\"couchbase:\/\/\" + os.Getenv(\"DB_HOST\"))\r\n\tcluster.Authenticate(gocb.PasswordAuthenticator{Username: os.Getenv(\"DB_USER\"), Password: os.Getenv(\"DB_PASS\")})\r\n\tbucket, _ = cluster.OpenBucket(os.Getenv(\"DB_BUCKET\"), \"\")\r\n\tfmt.Println(GetPersonDocument(\"8eaf1065-5bc7-49b5-8f04-c6a33472d9d5\"))\r\n\tCreatePersonDocument(\"blawson\", Person{Type: \"person\", Firstname: \"Brett\", Lastname: \"Lawson\"})\r\n}<\/pre>\n<p>O c\u00f3digo acima \u00e9 simples, mas sofrer\u00e1 altera\u00e7\u00f5es significativas \u00e0 medida que avan\u00e7armos neste tutorial. Por enquanto, vamos descobrir o que ele faz.<\/p>\n<p>Como estamos usando o Couchbase, precisamos ter obtido o Go SDK. Ele pode ser instalado executando o seguinte:<\/p>\n<pre class=\"lang:default decode:true\">go get gopkg.in\/couchbase\/gocb.v1<\/pre>\n<p>Com o Go SDK instalado, podemos adicion\u00e1-lo \u00e0s importa\u00e7\u00f5es do nosso projeto.<\/p>\n<p>O projeto ter\u00e1 duas fun\u00e7\u00f5es muito simples. Haver\u00e1 uma fun\u00e7\u00e3o para recuperar um documento e uma fun\u00e7\u00e3o para criar um documento. Cada documento ter\u00e1 a fun\u00e7\u00e3o <code>Pessoa<\/code> conforme definido no modelo <code>estrutura<\/code>.<\/p>\n<pre class=\"lang:default decode:true\">func main() {\r\n\tfmt.Println(\"Starting the application...\")\r\n\tcluster, _ := gocb.Connect(\"couchbase:\/\/\" + os.Getenv(\"DB_HOST\"))\r\n\tcluster.Authenticate(gocb.PasswordAuthenticator{Username: os.Getenv(\"DB_USER\"), Password: os.Getenv(\"DB_PASS\")})\r\n\tbucket, _ = cluster.OpenBucket(os.Getenv(\"DB_BUCKET\"), \"\")\r\n\tfmt.Println(GetPersonDocument(\"8eaf1065-5bc7-49b5-8f04-c6a33472d9d5\"))\r\n\tCreatePersonDocument(\"blawson\", Person{Type: \"person\", Firstname: \"Brett\", Lastname: \"Lawson\"})\r\n}<\/pre>\n<p>Quando o aplicativo for iniciado, ele se conectar\u00e1 a um cluster do Couchbase, conforme especificado pelas vari\u00e1veis de ambiente. Da mesma forma, uma conta RBAC ser\u00e1 autenticada e um bucket ser\u00e1 aberto.<\/p>\n<p>Depois que o banco de dados estiver pronto, primeiro obtemos um documento com base em um ID:<\/p>\n<pre class=\"lang:default decode:true\">func GetPersonDocument(key string) (interface{}, error) {\r\n\tvar data interface{}\r\n\t_, err := bucket.Get(key, &amp;data)\r\n\tif err != nil {\r\n\t\treturn nil, err\r\n\t}\r\n\treturn data, nil\r\n}<\/pre>\n<p>Supondo que o documento exista, ele ser\u00e1 retornado. Depois que o documento \u00e9 recuperado, inserimos um novo documento no banco de dados.<\/p>\n<pre class=\"lang:default decode:true\">func CreatePersonDocument(key string, data interface{}) (interface{}, error) {\r\n\t_, err := bucket.Insert(key, data, 0)\r\n\tif err != nil {\r\n\t\treturn nil, err\r\n\t}\r\n\treturn data, nil\r\n}<\/pre>\n<p>Agora voc\u00ea deve estar se perguntando por que estamos criando fun\u00e7\u00f5es para isso. Quero dizer, n\u00e3o estamos fazendo nada de especial al\u00e9m de usar o SDK real.<\/p>\n<p>Use sua imagina\u00e7\u00e3o com essas fun\u00e7\u00f5es. Suponha que elas sejam complexas porque estaremos escrevendo casos de teste para elas. Neste exemplo, elas s\u00e3o simples para facilitar a compreens\u00e3o.<\/p>\n<h2>Projetando testes de unidade com dados de simula\u00e7\u00e3o<\/h2>\n<p>Temos uma base para o nosso projeto, portanto, podemos come\u00e7ar a pensar em escrever casos de teste para o nosso aplicativo. Antes de come\u00e7armos a escrever testes, vamos fazer algumas altera\u00e7\u00f5es no arquivo\u00a0<strong>main.go<\/strong> que acabamos de criar.<\/p>\n<p>Abra o\u00a0<strong>main.go<\/strong> e inclua o seguinte:<\/p>\n<pre class=\"lang:default decode:true\">package main\r\n\r\nimport (\r\n\t\"fmt\"\r\n\t\"os\"\r\n\r\n\tgocb \"gopkg.in\/couchbase\/gocb.v1\"\r\n)\r\n\r\ntype BucketInterface interface {\r\n\tGet(key string, value interface{}) (gocb.Cas, error)\r\n\tInsert(key string, value interface{}, expiry uint32) (gocb.Cas, error)\r\n}\r\n\r\ntype Database struct {\r\n\tbucket BucketInterface\r\n}\r\n\r\ntype Person struct {\r\n\tType      string `json:\"type\"`\r\n\tFirstname string `json:\"firstname\"`\r\n\tLastname  string `json:\"lastname\"`\r\n}\r\n\r\nvar bucket BucketInterface\r\n\r\nfunc (d Database) GetPersonDocument(key string) (interface{}, error) {\r\n\tvar data interface{}\r\n\t_, err := d.bucket.Get(key, &amp;data)\r\n\tif err != nil {\r\n\t\treturn nil, err\r\n\t}\r\n\treturn data, nil\r\n}\r\n\r\nfunc (d Database) CreatePersonDocument(key string, data interface{}) (interface{}, error) {\r\n\t_, err := d.bucket.Insert(key, data, 0)\r\n\tif err != nil {\r\n\t\treturn nil, err\r\n\t}\r\n\treturn data, nil\r\n}\r\n\r\nfunc main() {\r\n\tfmt.Println(\"Starting the application...\")\r\n\tvar database Database\r\n\tcluster, _ := gocb.Connect(\"couchbase:\/\/\" + os.Getenv(\"DB_HOST\"))\r\n\tcluster.Authenticate(gocb.PasswordAuthenticator{Username: os.Getenv(\"DB_USER\"), Password: os.Getenv(\"DB_PASS\")})\r\n\tdatabase.bucket, _ = cluster.OpenBucket(os.Getenv(\"DB_BUCKET\"), \"\")\r\n\tfmt.Println(database.GetPersonDocument(\"8eaf1065-5bc7-49b5-8f04-c6a33472d9d5\"))\r\n\tdatabase.CreatePersonDocument(\"blawson\", Person{Type: \"person\", Firstname: \"Brett\", Lastname: \"Lawson\"})\r\n}<\/pre>\n<p>Observe que h\u00e1 algumas pequenas altera\u00e7\u00f5es no c\u00f3digo acima.<\/p>\n<p>Ao escrever testes para fun\u00e7\u00f5es que interagem com o banco de dados, provavelmente n\u00e3o \u00e9 uma boa ideia fazer testes com o banco de dados real. Em vez disso, devemos usar dados simulados. No entanto, queremos escrever testes sem passar por muitos obst\u00e1culos.<\/p>\n<p>Para testar facilmente, podemos criar uma interface que represente nosso bucket do Couchbase. Em nosso c\u00f3digo principal, usaremos um bucket real e, em nosso c\u00f3digo de teste, usaremos um bucket simulado.<\/p>\n<pre class=\"lang:default decode:true\">type BucketInterface interface {\r\n\tGet(key string, value interface{}) (gocb.Cas, error)\r\n\tInsert(key string, value interface{}, expiry uint32) (gocb.Cas, error)\r\n}\r\n\r\ntype Database struct {\r\n\tbucket BucketInterface\r\n}<\/pre>\n<p>Em nosso exemplo, a interface do nosso bucket inclui apenas duas das muitas fun\u00e7\u00f5es poss\u00edveis do SDK. Essa interface corresponde ao que ver\u00edamos no SDK real.<\/p>\n<p>As duas fun\u00e7\u00f5es que criamos agora fazem parte do <code>Banco de dados<\/code> classe.<\/p>\n<p>Criar um\u00a0<strong>main_test.go<\/strong> em seu projeto e certifique-se de que ele contenha o seguinte c\u00f3digo:<\/p>\n<pre class=\"lang:default decode:true\">package main\r\n\r\nimport (\r\n\t\"encoding\/json\"\r\n\t\"os\"\r\n\t\"testing\"\r\n\r\n\t\"github.com\/mitchellh\/mapstructure\"\r\n\tgocb \"gopkg.in\/couchbase\/gocb.v1\"\r\n)\r\n\r\ntype MockBucket struct{}\r\n\r\nvar testdatabase Database\r\n\r\nfunc convert(start interface{}, end interface{}) error {\r\n\tbytes, err := json.Marshal(start)\r\n\tif err != nil {\r\n\t\treturn err\r\n\t}\r\n\terr = json.Unmarshal(bytes, end)\r\n\tif err != nil {\r\n\t\treturn err\r\n\t}\r\n\treturn nil\r\n}\r\n\r\nfunc (b MockBucket) Get(key string, value interface{}) (gocb.Cas, error) {\r\n\tswitch key {\r\n\tcase \"nraboy\":\r\n\t\terr := convert(Person{Type: \"person\", Firstname: \"Nic\", Lastname: \"Raboy\"}, value)\r\n\t\tif err != nil {\r\n\t\t\treturn 0, err\r\n\t\t}\r\n\tdefault:\r\n\t\treturn 0, gocb.ErrKeyNotFound\r\n\t}\r\n\treturn 1, nil\r\n}\r\n\r\nfunc (b MockBucket) Insert(key string, value interface{}, expiry uint32) (gocb.Cas, error) {\r\n\tswitch key {\r\n\tcase \"nraboy\":\r\n\t\treturn 0, gocb.ErrKeyExists\r\n\t}\r\n\treturn 1, nil\r\n}\r\n\r\nfunc TestMain(m *testing.M) {\r\n\ttestdatabase.bucket = &amp;MockBucket{}\r\n\tos.Exit(m.Run())\r\n}\r\n\r\nfunc TestGetPersonDocument(t *testing.T) {\r\n\tdata, err := testdatabase.GetPersonDocument(\"nraboy\")\r\n\tif err != nil {\r\n\t\tt.Fatalf(\"Expected `err` to be `%s`, but got `%s`\", \"nil\", err)\r\n\t}\r\n\tvar person Person\r\n\tmapstructure.Decode(data, &amp;person)\r\n\tif person.Type != \"person\" {\r\n\t\tt.Fatalf(\"Expected `type` to be %s, but got %s\", \"person\", person.Type)\r\n\t}\r\n}\r\n\r\nfunc TestCreatePersonDocument(t *testing.T) {\r\n\t_, err := testdatabase.CreatePersonDocument(\"blawson\", Person{Type: \"person\", Firstname: \"Brett\", Lastname: \"Lawson\"})\r\n\tif err != nil {\r\n\t\tt.Fatalf(\"Expected `err` to be `%s`, but got `%s`\", \"nil\", err)\r\n\t}\r\n}<\/pre>\n<p>O c\u00f3digo acima \u00e9 realmente onde a m\u00e1gica entra em nosso projeto. Ele usa uma mistura de c\u00f3digo do arquivo pai e c\u00f3digo de teste personalizado.<\/p>\n<p>Veja, por exemplo, o seguinte:<\/p>\n<pre class=\"lang:default decode:true\">type MockBucket struct{}\r\n\r\nvar testdatabase Database<\/pre>\n<p>Ao testar, n\u00e3o vamos trabalhar com um bucket real do Couchbase, portanto, temos que criar nosso pr\u00f3prio <code>estrutura<\/code>. Estaremos usando o <code>Banco de dados<\/code>\u00a0do arquivo pai e usa a estrutura de dados <code>BucketInterface<\/code>.<\/p>\n<p>Quando os testes come\u00e7arem, poderemos criar nosso bucket fict\u00edcio:<\/p>\n<pre class=\"lang:default decode:true\">func TestMain(m *testing.M) {\r\n\ttestdatabase.bucket = &amp;MockBucket{}\r\n\tos.Exit(m.Run())\r\n}<\/pre>\n<p>Agora, como nosso balde de simula\u00e7\u00e3o n\u00e3o tem nenhuma fun\u00e7\u00e3o como o balde real, temos de criar as fun\u00e7\u00f5es conforme definido em nossa interface. Em outras palavras, temos que criar uma fun\u00e7\u00e3o <code>Inserir<\/code> e um <code>Obter<\/code> fun\u00e7\u00e3o.<\/p>\n<p>Come\u00e7ando com o <code>Inserir<\/code> fun\u00e7\u00e3o:<\/p>\n<pre class=\"lang:default decode:true\">func (b MockBucket) Insert(key string, value interface{}, expiry uint32) (gocb.Cas, error) {\r\n\tswitch key {\r\n\tcase \"nraboy\":\r\n\t\treturn 0, gocb.ErrKeyExists\r\n\t}\r\n\treturn 1, nil\r\n}<\/pre>\n<p>Nosso teste ser\u00e1 simples. Vamos tentar inserir qualquer documento, exceto um com uma chave de <code>garoto<\/code>. O teste ser\u00e1 bem-sucedido ou reprovado com base na chave.<\/p>\n<p>O <code>Obter<\/code> funciona de maneira semelhante.<\/p>\n<pre class=\"lang:default decode:true\">func convert(start interface{}, end interface{}) error {\r\n\tbytes, err := json.Marshal(start)\r\n\tif err != nil {\r\n\t\treturn err\r\n\t}\r\n\terr = json.Unmarshal(bytes, end)\r\n\tif err != nil {\r\n\t\treturn err\r\n\t}\r\n\treturn nil\r\n}\r\n\r\nfunc (b MockBucket) Get(key string, value interface{}) (gocb.Cas, error) {\r\n\tswitch key {\r\n\tcase \"nraboy\":\r\n\t\terr := convert(Person{Type: \"person\", Firstname: \"Nic\", Lastname: \"Raboy\"}, value)\r\n\t\tif err != nil {\r\n\t\t\treturn 0, err\r\n\t\t}\r\n\tdefault:\r\n\t\treturn 0, gocb.ErrKeyNotFound\r\n\t}\r\n\treturn 1, nil\r\n}<\/pre>\n<p>Ao tentar obter um documento, estamos esperando uma chave de <code>garoto<\/code>. Se a chave correta tiver sido fornecida, retorne alguns dados organizados por nosso <code>converter<\/code> caso contr\u00e1rio, retornar\u00e1 um erro.<\/p>\n<p>Novamente, essas s\u00e3o vers\u00f5es simuladas do que encontrar\u00edamos no Go SDK para opera\u00e7\u00f5es de balde. Com as fun\u00e7\u00f5es de interface criadas, podemos escrever nossas duas fun\u00e7\u00f5es de teste.<\/p>\n<pre class=\"lang:default decode:true\">func TestGetPersonDocument(t *testing.T) {\r\n\tdata, err := testdatabase.GetPersonDocument(\"nraboy\")\r\n\tif err != nil {\r\n\t\tt.Fatalf(\"Expected `err` to be `%s`, but got `%s`\", \"nil\", err)\r\n\t}\r\n\tvar person Person\r\n\tmapstructure.Decode(data, &amp;person)\r\n\tif person.Type != \"person\" {\r\n\t\tt.Fatalf(\"Expected `type` to be %s, but got %s\", \"person\", person.Type)\r\n\t}\r\n}<\/pre>\n<p>O <code>TestGetPersonDocument<\/code> usar\u00e1 nosso <code>banco de dados de teste<\/code> que usa o mock bucket. No entanto, ele usa a vari\u00e1vel <code>GetPersonDocument<\/code> do\u00a0<strong>main.go<\/strong> arquivo. Lembre-se de que a nossa fun\u00e7\u00e3o principal poderia ser muito mais complexa, mas a parte do banco de dados agora \u00e9 um mock.<\/p>\n<p>O resultado de nossa fun\u00e7\u00e3o ser\u00e1 decodificado no <code>Pessoa<\/code> usando a estrutura de dados <a href=\"https:\/\/github.com\/mitchellh\/mapstructure\" target=\"_blank\" rel=\"noopener\">estrutura do mapa<\/a> pacote. Mais informa\u00e7\u00f5es sobre o uso do pacote mapstructure podem ser lidas em <a href=\"https:\/\/www.thepolyglotdeveloper.com\/2017\/04\/decode-map-values-native-golang-structures\/\" target=\"_blank\" rel=\"noopener\">aqui<\/a>.<\/p>\n<pre class=\"lang:default decode:true\">func TestCreatePersonDocument(t *testing.T) {\r\n\t_, err := testdatabase.CreatePersonDocument(\"blawson\", Person{Type: \"person\", Firstname: \"Brett\", Lastname: \"Lawson\"})\r\n\tif err != nil {\r\n\t\tt.Fatalf(\"Expected `err` to be `%s`, but got `%s`\", \"nil\", err)\r\n\t}\r\n}<\/pre>\n<p>O <code>TestCreatePersonDocument<\/code> segue a mesma estrat\u00e9gia. Estamos usando o balde simulado, mas o balde real <code>CreatePersonDocument<\/code> fun\u00e7\u00e3o. A fun\u00e7\u00e3o <code>Inserir<\/code> usar\u00e1 o que criamos em nosso teste.<\/p>\n<p>N\u00e3o h\u00e1 muito o que fazer para testar um aplicativo Golang que inclui intera\u00e7\u00e3o com o banco de dados. Sua melhor aposta \u00e9 criar uma interface e usar suas pr\u00f3prias vers\u00f5es de simula\u00e7\u00e3o personalizadas das fun\u00e7\u00f5es e dos dados.<\/p>\n<h2>Cria\u00e7\u00e3o de uma configura\u00e7\u00e3o YAML para o Travis CI<\/h2>\n<p>Portanto, temos nosso aplicativo Go com alguns testes de unidade. Agora precisamos usar o Travis CI para testar automaticamente nosso aplicativo e implant\u00e1-lo se for bem-sucedido.<\/p>\n<p>O Travis CI funciona a partir de um arquivo de configura\u00e7\u00e3o YAML. Veja a configura\u00e7\u00e3o a seguir, por exemplo:<\/p>\n<pre class=\"lang:default decode:true\">language: go\r\ngo:\r\n    - 1.8\r\nbefore_script:\r\n    - sudo apt-get install -qq sshpass\r\nscript:\r\n    - go test -v\r\n    - go build\r\nafter_success:\r\n    - sshpass -p $SSH_PASS scp -o stricthostkeychecking=no golang-ci-example $SSH_USER@$SSH_HOST:~\/\r\n    - sshpass -p $SSH_PASS ssh -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST DB_HOST=$DB_HOST DB_USER=$DB_USER DB_PASS=$DB_PASS DB_BUCKET=$DB_BUCKET .\/golang-ci-example\r\nenv:\r\n    global:\r\nnotifications:\r\n    on_success: never\r\n    on_failure: never<\/pre>\n<p>A configura\u00e7\u00e3o acima diz que estamos usando o Go 1.8. Antes de come\u00e7armos a executar os scripts, precisamos fazer o download de um pacote necess\u00e1rio. Precisamos do <code>sshpass<\/code> que nos permite usar SSH com senhas de texto simples. No final, voc\u00ea provavelmente desejar\u00e1 usar chaves, mas, para este exemplo, n\u00e3o h\u00e1 problema.<\/p>\n<p>Depois de <code>sshpass<\/code> foi baixado, precisamos executar nossos testes. Isso \u00e9 feito na se\u00e7\u00e3o <code>roteiros<\/code> se\u00e7\u00e3o. Depois que o primeiro script for conclu\u00eddo, poderemos criar nosso projeto.<\/p>\n<p>Supondo que os dois scripts tenham sido conclu\u00eddos com \u00eaxito, queremos nos concentrar na implementa\u00e7\u00e3o.<\/p>\n<pre class=\"lang:default decode:true\">after_success:\r\n    - sshpass -p $SSH_PASS scp -o stricthostkeychecking=no golang-ci-example $SSH_USER@$SSH_HOST:~\/\r\n    - sshpass -p $SSH_PASS ssh -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST DB_HOST=$DB_HOST DB_USER=$DB_USER DB_PASS=$DB_PASS DB_BUCKET=$DB_BUCKET .\/golang-ci-example<\/pre>\n<p>Dois comandos diferentes s\u00e3o executados para a implementa\u00e7\u00e3o. O primeiro comando copiar\u00e1 o bin\u00e1rio para um servidor remoto e o segundo comando executar\u00e1 esse arquivo no servidor remoto.<\/p>\n<p>Ambos os comandos de implanta\u00e7\u00e3o fazem refer\u00eancia a vari\u00e1veis de ambiente no processo de CI\/CD que s\u00e3o posteriormente passadas para o servidor.<\/p>\n<p>Agora, voc\u00ea notar\u00e1 que n\u00e3o definimos nenhuma vari\u00e1vel de ambiente. Essas vari\u00e1veis s\u00e3o confidenciais e n\u00e3o devem ser texto simples em nosso reposit\u00f3rio Git. Em vez disso, podemos usar segredos com o Travis CI.<\/p>\n<p>Fa\u00e7a o download do <a href=\"https:\/\/docs.travis-ci.com\/user\/encryption-keys\/#Usage\" target=\"_blank\" rel=\"noopener\">travis<\/a> CLI seguindo a documenta\u00e7\u00e3o do Travis CI. Com a ferramenta instalada, execute o seguinte:<\/p>\n<pre class=\"lang:default decode:true\">travis encrypt SSH_HOST=YOUR_REMOTE_SERVER --add\r\ntravis encrypt SSH_USER=YOUR_REMOTE_SERVER_USER --add\r\ntravis encrypt SSH_PASS=YOUR_REMOTE_SERVER_PASS --add\r\n\r\ntravis encrypt DB_HOST=YOUR_COUCHBASE_SERVER --add\r\ntravis encrypt DB_USER=YOUR_COUCHBASE_SERVER_USER --add\r\ntravis encrypt DB_PASS=YOUR_COUCHBASE_SERVER_PASS --add\r\ntravis encrypt DB_BUCKET=YOUR_COUCHBASE_BUCKET --add<\/pre>\n<p>Em vez de adicionar todas as suas informa\u00e7\u00f5es como texto simples no arquivo YAML, elas s\u00e3o criptografadas e podem ser compreendidas pelo Travis CI. A configura\u00e7\u00e3o YAML que ele adiciona ter\u00e1 a seguinte apar\u00eancia:<\/p>\n<pre class=\"lang:default decode:true\">env:\r\n    global:\r\n        - secure: C\/5OS6jDmcubVA\/AKmapQDON9YH4+eK31geLzcCz6DjoG0zDCWX3qas+y3thij3sQ6E+54fUGZO\/8AeoVykfyEfhLRICgVw4d7RjGbjPFqDABVOFTB+HXxRNk5mNWGz\/V07r4N\/tnM+XMzUBKxOtgNNL7G0SjEPS9ormJGUbH3pYwnlTpzOUXHzvJ0x8Ynk7vC3Bfg5X0ALpNtjK7Wc0WCOCxhnDraUcWiBR3kp43QPac9nw\/eiSicLz1Y88ToxrXF2o6aPJqCrP0cpEDAMmtB89j14OIUDmaULssPk6WWWAeE4CvaqOlRG+gr5j2z9UgEfO6DoaIcL6TZQDCOQQix1f+5AMfexOFVn6oUO8O4x1wtfYwZwnajZ+O4R3ZKb1nHg1rY16m8O61yB0wdoaSP6NVn\/lyGkwmz7tNWGhGoxMgvG9U6yZuOYqwseP67y2y99zg94kR4WNF7NeH5YvaZo53d5pgPRMy\/0w15wJRJFgK3ef87EgMRWCJqVTEOw0bo+SQRPvDZRa7MgraxoZRkW2FKqYShWb7Ch0FlTTAY3ZCfynG+mXcDjMbaDWaUkea8KIfb7r7\/a8vDF5bXwNGDkQkbcZEMh46CnZxiLWgqsviBlISWuQAN1VgBLSI\/O\/uhJPHJzNGyhotDQf9W6Y+DiKqW40z3rAf4ZB9Li4+b4=\r\n        - secure: Pcv4MzEb0LD3LV9dtfevGwdI8wgkSAkgSq+lMByx6eQOLvA9mc4PVFin6A2Dc1FpObSuZfDLhr\/eGuFg8TbaY7KncPc7r\/OrPsSb9xCN9xPRlHP7mC+3t1NWjdGt6lVI647hlFQBs+MO8OHEyUquE6XHUZ8mnYe13TychlOM1VG+M2luyA46hEBMrUTId6CgsytqqCGWNqqZ5HBY01\/ne4qxQUX3LI3dPUThFjpKqYqLBx2S7FlMDhOYL01XPQ+yQ2CWWCzCau876IM5Mzey73brj4XE6SerFi6tBxLFtk7LxVa+6JvSi5tLZZ91kf6o6P7WD6O0q4T48BeUg5ewGFbX0+JF5YO7OA0ZAT3n8rKsfZCjiAO4GtHRcG0wV1Uh+etJSoWqR0+dZk4g7L9lIOOKwQiTl+7PoMYW3yhvbilLjcJ\/yektQJe\/NjSJFHqYH7EqeqbR3IAzjkxepZl6vwY08acoTdW918E27Lj7+mjUuUJSxT8aY8+DWQg6+RLSYXjLXsZ1m77VsYQ6gpEyXJYrnPnybVHX57GC7kXGonM4UAbtN3D80Qr37\/OX7i06MnJTa2xgkUVl\/HK7HfFlQsaX8yIC1zzaNHwNVKxIIGu\/hLM6GAPpF49y2ictmVbu0UKABcak4GdiF7zhrOF91p0Qui\/xcIcz2\/f+XBFU6vE=\r\n        - secure: KHaZKnIBoJmsVMYQUFAFAFbbqquM\/Stht0AZdsB6sbBvYnz2XLAaxpL89tBGp7IEibXW9\/C4t034oAQPaeF6AuODboetgvtjxGTOi+vcBqAj9l07IlajH89yi2Tx6zTq8DvyCKBjaNu0ocD70rplqEBZwa\/mttqw+YXKv29C4eunusho\/2Jcq+uztTJdiGZsy73NRAFFSLLezzTEQ4sLYc9v\/PYOiP\/BwcPzemj1DpQr8awly7LtQSj6QdTrjLotQmVTvdXsFHUcPsQdRlLKcy781Q5oP95inujB37vcusOjTru6bXYUzS8hMz\/JkUX4bocvd4yf1SLEmBbocHu6X4wmuI+JxD8WSBnkbJHjnWDPyEm5VRzq2rT+9hoe83XN9wm+im+bEfQUmYmyttCDmCogl+vaX337JaHrKESVtBlBRPUOlS6xM\/6gi8HT7EbG4Ir1qqNVGVbbdKemD+odcQqNQDVREkqSCOD0rdmXjJSpb8BSH5ftqF3lvfsVyO9fUkzxZfhL7O6pkiH4LGqwU1RaMKhlixQBhrjtRTLfluHR3\/9tZxKhyQHc\/pXV+wWHig2ziKVhk02c82fNAD5J4lpf8QK5wzWqBBnsPQ20\/gRXoqi3QkF66ZUKTy8r\/03NHeJtSraWOYE5\/6kzNSCcnL245l6r73fc5IJCa1+Ijmc=\r\n        - secure: o\/N\/\/U7qZJyERaGi89H00rdgma1ACL2O1vEgn\/qZdJx0OQk02Sj1w9H0pMawMcWlLCAlZZzwdnwkH604p76iSiTffknEZ0kfr\/YWise1ACeO2NLxMcn\/o+ch9Hjpuc9vWkMsFRqDv9WFYd6xRcAz8BRAeavhe3kykcBOacY7ZLGIc2NQarlhKXPY4xpPEhAhjnCrmsMq1ppCbnINAu8dLx4lyTCGF4FHYwPsCUylfgGI4Kr5gO1ikg7mLV1rL0RYmKm0MQrQbOuUrlnXdRaTbsBKhMBWDUjlmg+aeC4DPOcSTEvJ3YEhDk8bLDttr8RRhEUlgGkNNN21cpCBvbhSD6OaZdwFF6PFyd63CBSgi\/abv36iewjgGwjKoHdptkSiMQzYBe4qzjD4MupYwrgj8TibfW+Y21vzNtY6BnpXnuetCD41NgY5PZyLfQkvi6YcIi6MW9x4vc87EPhO8JcTMvchoQgg9LVv+BoA3Wf8qz1aRiLnctEeOwAdix6bGxh3JZqR+5HYvLSCdWrnwhKbWBgju3icYZ9odDnLfrDqPhcsPfU4BBUh+xU1khuv\/n3Vy27y81iqpWBb+iGH59IL+FPZDMeGETGZiAkDHiJxu9s3fr1VtK\/B8WGKqrGbKU3GOOm0JEfZJHDRmchDLOJoRlbubcljDnfSAFEMy19XWEI=\r\n        - secure: l0\/Z0FTznp9w2pmr1QxjTxtQsnaVUHZNDk+EBWyiTepxkkgH8ohDqM5jocaZQyMZmV3WUNG1phBD1S+MaF+ou1BIfHGKmnOm7OXujskgdvtvNzqFKCfkh30qcaipzM653VrZdatnU9zwzbgURWSkPXQ5B05yrs\/AH0sBOaIgl1J7JOXV6RZAOLkBahjMTSKc34ckBNt1Q6WpIKnzYqPdYpLpS8nmDZVszC7Fo4ykXsm7lloFJ43Ii+5D9culyGpq6z2eFvpALEYnixSkl3zUFNwuf1CIdsFBJThWdbYMlO6R2vi0N8QszMSLMc+Ry+HHm54E6IhbrReKCV8Rnho1DF4+0bmAbj7xNIl9uAFOOhuONLYzQLH+x7FxyjKJx8EiirgofO8EUdfEkXauIr+hufYboepMGjGIcUiO+VUXHo1w+o6GIHVGddxtnBU8ryctiZwUOkLJpR6ex6tltuJCFw5YzXvcLOf0+ZYoNZAFctc0DA0hpIAyv1ZoVGEpX+3Mi14zv7LYkLhPKnjc4MIm6mkQfMcBsVjK1aGow6ypDpQFcHKTNXOxNepD8uM9afoR11hhy8jPD8VtWNTn9vW+Szocoe65EbWmz3V0YDLmfCgm0Ltg4IanJOH6cEV8uUNYjHuj4X731dnmBa\/vlGDyhSeLCjzcuSkukmqVZhLUpMI=\r\n        - secure: VQE+9BAya6XAUBsGKF5kqCm1L6eO2mmaM9VmEx0u+xObUygjq32FN3i\/mQ6cs26SQJQ07XDBnwsnAhTY3\/u9ZP6hJrpY\/2Q2dOMuUHU6kx5gJhAGfnza8yv4cedCl54dSRf5zH5YdO7kb8jwhBFvjMJrbzCmnCuFrWbFKgLqOCqqykL51o48Q33kIbkbj+t8tmVu0JyyQ8kpBpgVgpilPWWeR2xtKkKEskU4Shpywjy02maOxgt6BHQFumdzPIT\/h2Bwb8qh74k8CrqQwvmA9Vxcg2qHCH9G8NEXbwd4BFxncET8FJfgqvCuuu3EWiT46EhG2xgI9\/1cgzlf16ZMnQIzhuSs6fnOlNlK2PJtijovVlQDxVpXJ863oWVpln5V3vfqGllJ9lEaF4TVuVQG3jsXGfX5j2BMwiLMvMF+o0Ym\/YUne84jCoJ5+ImJa9o0I+8qC32QV+OElJ\/BtCuB1koiCYz4cKcl5i\/6+0J0TSQKzj3\/RlZKndAgnAoT1qBQwL4oHG5ZWXJWO85BYwy\/9jBroGLASHR70oDPkmGR4Msgm+B\/qq520LljG72jA220IBnNK8LKXQpzn0rPaN9VwHz2HoSb0O7x6eagKzEoL0AiMOsIMyD1kA1xLWX6RAP8T1Mo1PP2Gv8lzcRCKcj5SMlw5I3ZLcT14EW4gxW1l8s=\r\n        - secure: RDgyGNdr2kpQzYT4hsCLH\/UyoxdIG83r37Fqg0J6rc7mY3u6sj62Btp20Z1f7Hh9R2e6tPZJcSY6NtT4fj6OcGQgHASAPjmYl6Fn+MFOcwIfS6Y2Pu8BGQlzTpDzeSqg\/JHNeStD29yervJuPGshrrZKeTECkV1PwHQMbRS+uENVoO4VM11dQXa+GWTznyrjItIKUabHSJ520QbheAnHJ1\/NkUnc824nTvwZoQ4zw9YgAE\/UvvHfyAZ4+3HjUsUaI1ZiD\/UHk2VjZsllp7dTPlW33a1MZL2MJD+wWtPmi6xVeNF2pIvX4TnhQYpQZ1oP5U6UZrFgLxe9doIpSgswPObR2pHUySg\/Ts\/jAY0O\/JfZH+SH0tyzrUrllLm4KirkHgiLbjcHGlzvjuGAOdwUgrEmVser7x3kKnj6IQiE9iAqm\/jzGsbS1M3zSY6Um1vyjyqPFXwF10HP7cvdA290Wrjrqov6o+H4N21ldBvZp1EQuyRsE8cPaVt8ik5ti0ZN9P\/8\/oZmvJsLHHGOoIkkusDy7m61H9GSNr1d52cPHiVJyEdKtQJPTRdoMirgz1wpJiY\/OCHzifxkuVuf1bBo1IjVbC5aG+5Halx2NPX5QW8Lfl2xJMprA1rvNnFLXiaX8hZUVDrvhA\/zNJFY8yu23pW0OInsJ7HAggUw+EHpaXM=<\/pre>\n<p>Isso \u00e9 algo que voc\u00ea pode manter em seu reposit\u00f3rio Git e se sentir seguro. Uma abordagem ainda mais segura seria usar chaves p\u00fablicas e privadas para SSH, mas isso \u00e9 adequado para este exemplo.<\/p>\n<p>Quando voc\u00ea enviar seu projeto, supondo que o tenha vinculado \u00e0 sua conta do Travis CI, o aplicativo ser\u00e1 testado e implantado automaticamente.<\/p>\n<h2>A import\u00e2ncia do NoSQL com a implanta\u00e7\u00e3o cont\u00ednua<\/h2>\n<p>Vimos como criar testes que usam dados simulados como um banco de dados. Entretanto, o que \u00e9 realmente conveniente \u00e9 que n\u00e3o precisamos criar scripts de atualiza\u00e7\u00e3o quando nossos dados s\u00e3o alterados. Em um banco de dados relacional, voc\u00ea teria de criar scripts de altera\u00e7\u00e3o para sua tabela. Com o Couchbase, se o seu modelo de dados precisar ser alterado, basta mudar para <code>estrutura<\/code> para <code>Pessoa<\/code> no c\u00f3digo.<\/p>\n<h2>Conclus\u00e3o<\/h2>\n<p>Voc\u00ea acabou de ver como usar o Travis CI para implantar continuamente seu projeto Golang que usa um <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/\" target=\"_blank\" rel=\"noopener\">Couchbase<\/a> Banco de dados NoSQL. Durante a fase de integra\u00e7\u00e3o cont\u00ednua, o aplicativo \u00e9 testado usando dados simulados. Quando os testes s\u00e3o aprovados e o projeto \u00e9 desenvolvido, ele \u00e9 enviado para um servidor remoto e executado.<\/p>\n<p>O exemplo usado neste tutorial pode ser encontrado em <a href=\"https:\/\/github.com\/couchbaselabs\/golang-ci-example\" target=\"_blank\" rel=\"noopener\">GitHub<\/a>. Observe apenas que o servidor remoto para o qual o projeto \u00e9 enviado foi removido.<\/p>\n<p>Se voc\u00ea estiver interessado em saber mais sobre Go com o Couchbase, confira o <a href=\"https:\/\/www.couchbase.com\/blog\/pt\/developers\/\" target=\"_blank\" rel=\"noopener\">Portal do desenvolvedor do Couchbase<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"<p>So you&#8217;ve been developing an application using the Go programming language with a team of developers for your organization. Best practice would say that you need to create proper tests and develop a continuous integration and deployment strategy. If you&#8217;ve [&hellip;]<\/p>","protected":false},"author":63,"featured_media":13873,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1815,1820],"tags":[1919,2031,1920,1567,2150,1413,1725],"ppma_author":[9032],"class_list":["post-4615","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-best-practices-and-tutorials","category-golang","tag-cd","tag-ci","tag-continuous-delivery","tag-continuous-deployment","tag-continuous-integration","tag-github","tag-nosql-database"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.7.1 (Yoast SEO v25.7) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Continuously Deploying a Golang Application Using Travis CI<\/title>\n<meta name=\"description\" content=\"Learn how to create a Go application that interacts with the NoSQL database, Couchbase, and how to use Travis CI for continuous integration and deployment.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/pt\/continuously-deploying-golang-application-using-travis-ci\/\" \/>\n<meta property=\"og:locale\" content=\"pt_BR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Continuously Deploying a Golang Application Using Travis CI\" \/>\n<meta property=\"og:description\" content=\"Learn how to create a Go application that interacts with the NoSQL database, Couchbase, and how to use Travis CI for continuous integration and deployment.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/pt\/continuously-deploying-golang-application-using-travis-ci\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/thepolyglotdeveloper\" \/>\n<meta property=\"article:published_time\" content=\"2018-02-13T16:35:07+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T05:49:05+00:00\" \/>\n<meta name=\"author\" content=\"Nic Raboy, Developer Advocate, Couchbase\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@nraboy\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Nic Raboy, Developer Advocate, Couchbase\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/\"},\"author\":{\"name\":\"Nic Raboy, Developer Advocate, Couchbase\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1\"},\"headline\":\"Continuously Deploying a Golang Application Using Travis CI\",\"datePublished\":\"2018-02-13T16:35:07+00:00\",\"dateModified\":\"2025-06-14T05:49:05+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/\"},\"wordCount\":1478,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"keywords\":[\"cd\",\"ci\",\"continuous delivery\",\"Continuous Deployment\",\"continuous integration\",\"GitHub\",\"NoSQL Database\"],\"articleSection\":[\"Best Practices and Tutorials\",\"GoLang\"],\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/\",\"name\":\"Continuously Deploying a Golang Application Using Travis CI\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"datePublished\":\"2018-02-13T16:35:07+00:00\",\"dateModified\":\"2025-06-14T05:49:05+00:00\",\"description\":\"Learn how to create a Go application that interacts with the NoSQL database, Couchbase, and how to use Travis CI for continuous integration and deployment.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/#breadcrumb\"},\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png\",\"width\":1800,\"height\":630},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Continuously Deploying a Golang Application Using Travis CI\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"pt-BR\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1\",\"name\":\"Nic Raboy, Developer Advocate, Couchbase\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/8863514d8bed0cf6080f23db40e00354\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g\",\"caption\":\"Nic Raboy, Developer Advocate, Couchbase\"},\"description\":\"Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.\",\"sameAs\":[\"https:\/\/www.thepolyglotdeveloper.com\",\"https:\/\/www.facebook.com\/thepolyglotdeveloper\",\"https:\/\/x.com\/nraboy\"],\"url\":\"https:\/\/www.couchbase.com\/blog\/pt\/author\/nic-raboy-2\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Implanta\u00e7\u00e3o cont\u00ednua de um aplicativo Golang usando o Travis CI","description":"Learn how to create a Go application that interacts with the NoSQL database, Couchbase, and how to use Travis CI for continuous integration and deployment.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/pt\/continuously-deploying-golang-application-using-travis-ci\/","og_locale":"pt_BR","og_type":"article","og_title":"Continuously Deploying a Golang Application Using Travis CI","og_description":"Learn how to create a Go application that interacts with the NoSQL database, Couchbase, and how to use Travis CI for continuous integration and deployment.","og_url":"https:\/\/www.couchbase.com\/blog\/pt\/continuously-deploying-golang-application-using-travis-ci\/","og_site_name":"The Couchbase Blog","article_author":"https:\/\/www.facebook.com\/thepolyglotdeveloper","article_published_time":"2018-02-13T16:35:07+00:00","article_modified_time":"2025-06-14T05:49:05+00:00","author":"Nic Raboy, Developer Advocate, Couchbase","twitter_card":"summary_large_image","twitter_creator":"@nraboy","twitter_misc":{"Written by":"Nic Raboy, Developer Advocate, Couchbase","Est. reading time":"7 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/"},"author":{"name":"Nic Raboy, Developer Advocate, Couchbase","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1"},"headline":"Continuously Deploying a Golang Application Using Travis CI","datePublished":"2018-02-13T16:35:07+00:00","dateModified":"2025-06-14T05:49:05+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/"},"wordCount":1478,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","keywords":["cd","ci","continuous delivery","Continuous Deployment","continuous integration","GitHub","NoSQL Database"],"articleSection":["Best Practices and Tutorials","GoLang"],"inLanguage":"pt-BR","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/","url":"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/","name":"Implanta\u00e7\u00e3o cont\u00ednua de um aplicativo Golang usando o Travis CI","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","datePublished":"2018-02-13T16:35:07+00:00","dateModified":"2025-06-14T05:49:05+00:00","description":"Learn how to create a Go application that interacts with the NoSQL database, Couchbase, and how to use Travis CI for continuous integration and deployment.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/#breadcrumb"},"inLanguage":"pt-BR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/"]}]},{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2022\/11\/couchbase-nosql-dbaas.png","width":1800,"height":630},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Continuously Deploying a Golang Application Using Travis CI"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"Blog do Couchbase","description":"Couchbase, o banco de dados NoSQL","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"pt-BR"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"Blog do Couchbase","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/bb545ebe83bb2d12f91095811d0a72e1","name":"Nic Raboy, defensor dos desenvolvedores, Couchbase","image":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/8863514d8bed0cf6080f23db40e00354","url":"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g","caption":"Nic Raboy, Developer Advocate, Couchbase"},"description":"Nic Raboy \u00e9 um defensor das modernas tecnologias de desenvolvimento m\u00f3vel e da Web. Ele tem experi\u00eancia em Java, JavaScript, Golang e uma variedade de estruturas, como Angular, NativeScript e Apache Cordova. Nic escreve sobre suas experi\u00eancias de desenvolvimento relacionadas a tornar o desenvolvimento m\u00f3vel e da Web mais f\u00e1cil de entender.","sameAs":["https:\/\/www.thepolyglotdeveloper.com","https:\/\/www.facebook.com\/thepolyglotdeveloper","https:\/\/x.com\/nraboy"],"url":"https:\/\/www.couchbase.com\/blog\/pt\/author\/nic-raboy-2\/"}]}},"authors":[{"term_id":9032,"user_id":63,"is_guest":0,"slug":"nic-raboy-2","display_name":"Nic Raboy, Developer Advocate, Couchbase","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/bedeb68368d4681aca4c74fe5f697f0c423b80d498ec50fd915ba018b72c101f?s=96&d=mm&r=g","first_name":"Nic","last_name":"Raboy","user_url":"https:\/\/www.thepolyglotdeveloper.com","author_category":"","description":"Nic Raboy \u00e9 um defensor das modernas tecnologias de desenvolvimento m\u00f3vel e da Web. Ele tem experi\u00eancia em Java, JavaScript, Golang e uma variedade de estruturas, como Angular, NativeScript e Apache Cordova. Nic escreve sobre suas experi\u00eancias de desenvolvimento relacionadas a tornar o desenvolvimento m\u00f3vel e da Web mais f\u00e1cil de entender."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/4615","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/users\/63"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/comments?post=4615"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/4615\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/media?parent=4615"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/categories?post=4615"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/tags?post=4615"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/ppma_author?post=4615"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}