{"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\/continuously-deploying-golang-application-using-travis-ci\/","title":{"rendered":"Continuously Deploying a Golang Application Using Travis CI"},"content":{"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.<\/p>\n<p>If you&#8217;ve been keeping up with my tutorials, you&#8217;ll remember that I wrote about creating a <a href=\"https:\/\/www.couchbase.com\/blog\/create-continuous-deployment-pipeline-nodejs-jenkins\/\" target=\"_blank\" rel=\"noopener\">continuous deployment pipeline with Node.js and Jenkins<\/a>. This time around we&#8217;re going to change things up with the development technology and CI \/ CD service.<\/p>\n<p>We&#8217;re going to see how to continuously deploy a Golang application that interacts with <a href=\"https:\/\/www.couchbase.com\" target=\"_blank\" rel=\"noopener\">Couchbase<\/a> with the popular <a href=\"https:\/\/travis-ci.org\" target=\"_blank\" rel=\"noopener\">Travis CI<\/a> service.<\/p>\n<p><!--more--><\/p>\n<p>The goal of this tutorial is to help you create a Golang application that communicates with Couchbase. This application will have proper unit tests that will be used when Travis CI is triggered. If the tests are successful in Travis CI, the application will be automatically deployed to some remote server with SSH.<\/p>\n<p>As a prerequisite, you will need to have at least one Couchbase Server instance available to you. This Couchbase Server instance will be used during deployment.<\/p>\n<h2>Developing an Application with Go and Couchbase NoSQL<\/h2>\n<p>We&#8217;ll be creating a fresh Golang project for this example. Somewhere in your\u00a0<strong>$GOPATH<\/strong> create a file called\u00a0<strong>main.go<\/strong> and include the following:<\/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>The above code is simple, but will change significantly as we progress in this tutorial. For now, let&#8217;s figure out what it does.<\/p>\n<p>Because we&#8217;re using Couchbase, we need to have obtained the Go SDK. This can be installed by executing the following:<\/p>\n<pre class=\"lang:default decode:true \">go get gopkg.in\/couchbase\/gocb.v1<\/pre>\n<p>With the Go SDK installed, we can add it to our project imports.<\/p>\n<p>The project will have two very simple functions. There will be a function for retrieving a document and a function for creating a document. Each document will have the <code>Person<\/code> model as defined in the <code>struct<\/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>When the application starts, it will connect to a Couchbase cluster as specified by environment variables. Likewise an RBAC account will be authenticated and a bucket will be opened.<\/p>\n<p>After the database is good to go, we first get a document based on an 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>Assuming the document exists, it will be returned. After the document is retrieved, we insert a new document into the database.<\/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>Now you might be wondering, why we are creating functions for this at all. I mean we aren&#8217;t doing anything special beyond using the actual SDK.<\/p>\n<p>Use your imagination on these functions. Assume they are something complex because we&#8217;ll be writing test cases for them. They are simple in this example to remain easy to understand.<\/p>\n<h2>Designing Unit Tests with Mock Data<\/h2>\n<p>We have a foundation to our project, so we can start thinking about writing test cases for our application. Before we start writing tests, let&#8217;s make a few changes to the\u00a0<strong>main.go<\/strong> file that we had just created.<\/p>\n<p>Open the\u00a0<strong>main.go<\/strong> file and include the following:<\/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>Notice that there are some slight changes to the above code.<\/p>\n<p>When writing tests for functions that interact with your database, it probably isn&#8217;t a good idea to test against your actual database. Instead we&#8217;re going to want to use mock data. However, we&#8217;re going to want to write tests without jumping through too many hoops.<\/p>\n<p>To test easily, we can create an interface that represents our Couchbase bucket. In our main code, we&#8217;ll use an actual bucket and in our test code we&#8217;ll use a mock bucket.<\/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>In our example, the interface for our bucket only includes two of the many possible SDK functions. This interface matches what we&#8217;d see in the actual SDK.<\/p>\n<p>The two functions that we had created are now part of the <code>Database<\/code> class.<\/p>\n<p>Create a\u00a0<strong>main_test.go<\/strong> file in your project and make sure it contains the following code:<\/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>The above code is really where the magic comes in for our project. It uses a mixture of code from the parent file and custom test code.<\/p>\n<p>Take the following for example:<\/p>\n<pre class=\"lang:default decode:true \">type MockBucket struct{}\r\n\r\nvar testdatabase Database<\/pre>\n<p>When testing, we aren&#8217;t going to be working with an actual Couchbase bucket, so we have to create our own dummy <code>struct<\/code>. We will be using the <code>Database<\/code>\u00a0data structure from the parent file and it uses the <code>BucketInterface<\/code>.<\/p>\n<p>When the tests start, we can create our dummy bucket:<\/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>Now, since our mock bucket doesn&#8217;t have any functions like the real bucket, we have to create the functions as defined in our interface. In other words, we have to create an <code>Insert<\/code> and a <code>Get<\/code> function.<\/p>\n<p>Starting with the <code>Insert<\/code> function:<\/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>Our test is going to be simple. We&#8217;re going to try to insert any document except one with a key of <code>nraboy<\/code>. The test will either succeed or fail based on the key.<\/p>\n<p>The <code>Get<\/code> function works in a similar fashion.<\/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>When trying to get a document, we are expecting a key of <code>nraboy<\/code>. If the correct key was provided, return some data marshalled by our <code>convert<\/code> function, otherwise return an error.<\/p>\n<p>Again, these are mock versions of what we&#8217;d find in the Go SDK for bucket operations. With the interface functions created, we can write our two test functions.<\/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>The <code>TestGetPersonDocument<\/code> will use our <code>testdatabase<\/code> variable which uses the mock bucket. However, it uses the <code>GetPersonDocument<\/code> from the\u00a0<strong>main.go<\/strong> file. Remember, our parent function could be way more complex, but the database stuff is now mock.<\/p>\n<p>The result of our function will be decoded into the <code>Person<\/code> data structure using the <a href=\"https:\/\/github.com\/mitchellh\/mapstructure\" target=\"_blank\" rel=\"noopener\">mapstructure<\/a> package. More information on using the mapstructure package can be read about <a href=\"https:\/\/www.thepolyglotdeveloper.com\/2017\/04\/decode-map-values-native-golang-structures\/\" target=\"_blank\" rel=\"noopener\">here<\/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>The <code>TestCreatePersonDocument<\/code> function follows the same strategy. We are using the mock bucket, but the very real <code>CreatePersonDocument<\/code> function. The <code>Insert<\/code> will use what we had created in our test.<\/p>\n<p>There isn&#8217;t too much to testing a Golang application that includes database interaction. Your best bet is to create an interface and use your own custom mock versions of the functions and data.<\/p>\n<h2>Creating a YAML Configuration for Travis CI<\/h2>\n<p>So we have our Go application with a few unit tests. Now we need to be able to use Travis CI to automatically test our application and deploy it if successful.<\/p>\n<p>Travis CI functions off a YAML configuration file. Take the following configuration for example:<\/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>The above configuration says that we are using Go 1.8. Before we start executing scripts, we need to download a necessary package. We need <code>sshpass<\/code> which allows us to SSH with plaintext passwords. In the end you&#8217;ll probably want to use keys, but for this example it is fine.<\/p>\n<p>After <code>sshpass<\/code> has downloaded, we need to run our tests. This is done in the <code>scripts<\/code> section. After the first script finishes, we can build our project.<\/p>\n<p>Assuming both scripts have completed successfully, we want to focus on the deployment.<\/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>Two different commands are executed for deployment. The first command will copy the binary to a remote server and the second command will run that file on the remote server.<\/p>\n<p>Both deployment commands reference environment variables in the CI \/ CD process that are later passed to the server.<\/p>\n<p>Now, you&#8217;ll notice that we haven&#8217;t set any environment variables. These variables are sensitive and shouldn&#8217;t be plain text within our Git repository. Instead we can use secrets with Travis CI.<\/p>\n<p>Download the <a href=\"https:\/\/docs.travis-ci.com\/user\/encryption-keys\/#Usage\" target=\"_blank\" rel=\"noopener\">travis<\/a> CLI tool by following the Travis CI documentation. With the tool installed, execute the following:<\/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>Instead of adding all your information as plain text in the YAML file, it is encrypted and can be understood by Travis CI. The YAML configuration it adds will look something like this:<\/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>This is something you can keep in your Git repository and feel safe. An even safer approach would be to use public and private keys for SSH, but this is fine for this example.<\/p>\n<p>When you push your project, assuming you&#8217;ve linked it in your Travis CI account, the application will test and deploy automatically.<\/p>\n<h2>The Significance of NoSQL with Continuous Deployment<\/h2>\n<p>We saw how to create tests that use mock data as a database. However, what is really convenient is that we don&#8217;t need to create upgrade scripts when our data changes. In a relational database you&#8217;d have to create alter scripts for your table. With Couchbase, if your data model needs to change, just change to <code>struct<\/code> for <code>Person<\/code> in the code.<\/p>\n<h2>Conclusion<\/h2>\n<p>You just saw how to use Travis CI to continuously deploy your Golang project that uses a <a href=\"https:\/\/www.couchbase.com\" target=\"_blank\" rel=\"noopener\">Couchbase<\/a> NoSQL database. During the continuous integration phase, the application is tested using mock data. When the tests pass and the project is built, it is pushed to a remote server and ran.<\/p>\n<p>The example used in this tutorial can be found on <a href=\"https:\/\/github.com\/couchbaselabs\/golang-ci-example\" target=\"_blank\" rel=\"noopener\">GitHub<\/a>. Just note that the remote server that the project is pushed to has been removed.<\/p>\n<p>If you&#8217;re interested in learning more about Go with Couchbase, check out the <a href=\"https:\/\/www.couchbase.com\/developers\/\" target=\"_blank\" rel=\"noopener\">Couchbase Developer Portal<\/a>.<\/p>\n","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>\n","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 v26.0 (Yoast SEO v26.0) - 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\/continuously-deploying-golang-application-using-travis-ci\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\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\/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 minutes\" \/>\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\":\"en-US\",\"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\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@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\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@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\":\"en-US\",\"@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\/author\/nic-raboy-2\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Continuously Deploying a Golang Application Using 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\/continuously-deploying-golang-application-using-travis-ci\/","og_locale":"en_US","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\/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 minutes"},"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":"en-US","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":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/continuously-deploying-golang-application-using-travis-ci\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@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":"en-US"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"The Couchbase Blog","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@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":"en-US","@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\/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","author_category":"","last_name":"Raboy","first_name":"Nic","job_title":"","user_url":"https:\/\/www.thepolyglotdeveloper.com","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."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/4615","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/users\/63"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/comments?post=4615"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/4615\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media\/13873"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media?parent=4615"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=4615"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=4615"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=4615"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}