Golang应用如何通过GitHub、Travis和Heroku部署MongoDB支持的服务

Golang应用如何通过GitHub、Travis和Heroku部署MongoDB支持的服务 我为我的日记应用程序编写了一个服务器,并希望将其部署在 Heroku 上,但前提是它需要通过 Travis CI 的单元测试。

关键在于,我的应用程序还依赖于一个正常运行的 MongoDB 版本。

有没有人之前做过这种 GitHub-Travis-Heroku 的配置?您有什么推荐的资源或项目可以供我学习吗?

2 回复

模拟 MongoDB。

更多关于Golang应用如何通过GitHub、Travis和Heroku部署MongoDB支持的服务的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


对于通过GitHub、Travis CI和Heroku部署MongoDB支持的Golang服务,以下是完整的配置方案:

1. 项目结构示例

my-diary-app/
├── main.go
├── go.mod
├── go.sum
├── .travis.yml
├── Procfile
├── mongodb_test.go
└── .env.example

2. main.go 示例(MongoDB集成)

package main

import (
    "context"
    "fmt"
    "log"
    "net/http"
    "os"
    "time"
    
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
    "go.mongodb.org/mongo-driver/bson"
)

var client *mongo.Client

type DiaryEntry struct {
    ID        string    `bson:"_id,omitempty"`
    Title     string    `bson:"title"`
    Content   string    `bson:"content"`
    CreatedAt time.Time `bson:"created_at"`
}

func initMongoDB() {
    mongoURI := os.Getenv("MONGODB_URI")
    if mongoURI == "" {
        mongoURI = "mongodb://localhost:27017"
    }
    
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    
    var err error
    client, err = mongo.Connect(ctx, options.Client().ApplyURI(mongoURI))
    if err != nil {
        log.Fatal(err)
    }
    
    err = client.Ping(ctx, nil)
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Println("Connected to MongoDB!")
}

func diaryHandler(w http.ResponseWriter, r *http.Request) {
    collection := client.Database("diary").Collection("entries")
    
    switch r.Method {
    case "GET":
        ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
        defer cancel()
        
        cursor, err := collection.Find(ctx, bson.M{})
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }
        defer cursor.Close(ctx)
        
        var entries []DiaryEntry
        if err = cursor.All(ctx, &entries); err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }
        
        fmt.Fprintf(w, "Found %d entries", len(entries))
        
    case "POST":
        // 处理日记创建逻辑
        fmt.Fprint(w, "Entry created")
    }
}

func main() {
    initMongoDB()
    
    http.HandleFunc("/diary", diaryHandler)
    
    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
    }
    
    log.Printf("Server starting on port %s", port)
    log.Fatal(http.ListenAndServe(":"+port, nil))
}

3. .travis.yml 配置

language: go
go:
  - "1.19"
  - "1.20"

services:
  - mongodb

env:
  - MONGODB_URI=mongodb://localhost:27017

before_script:
  - go mod download

script:
  - go test -v ./...
  - go build -v ./...

deploy:
  provider: heroku
  api_key:
    secure: $HEROKU_API_KEY
  app: your-heroku-app-name
  on:
    branch: main
  run:
    - "heroku config:set MONGODB_URI=$MONGODB_PROD_URI -a your-heroku-app-name"

4. 单元测试示例(mongodb_test.go)

package main

import (
    "context"
    "testing"
    "time"
    
    "go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

func TestMongoDBConnection(t *testing.T) {
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    
    client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://localhost:27017"))
    if err != nil {
        t.Fatalf("Failed to connect to MongoDB: %v", err)
    }
    defer client.Disconnect(ctx)
    
    err = client.Ping(ctx, nil)
    if err != nil {
        t.Fatalf("Failed to ping MongoDB: %v", err)
    }
}

func TestDiaryCRUD(t *testing.T) {
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()
    
    client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://localhost:27017"))
    if err != nil {
        t.Fatalf("Failed to connect: %v", err)
    }
    defer client.Disconnect(ctx)
    
    collection := client.Database("test_diary").Collection("entries")
    
    // 清理测试数据
    collection.Drop(ctx)
    
    // 测试插入
    entry := DiaryEntry{
        Title:     "Test Entry",
        Content:   "Test Content",
        CreatedAt: time.Now(),
    }
    
    result, err := collection.InsertOne(ctx, entry)
    if err != nil {
        t.Fatalf("Failed to insert: %v", err)
    }
    
    // 测试查询
    var retrievedEntry DiaryEntry
    err = collection.FindOne(ctx, bson.M{"_id": result.InsertedID}).Decode(&retrievedEntry)
    if err != nil {
        t.Fatalf("Failed to find entry: %v", err)
    }
    
    if retrievedEntry.Title != "Test Entry" {
        t.Errorf("Expected title 'Test Entry', got '%s'", retrievedEntry.Title)
    }
}

5. Procfile(Heroku部署)

web: ./my-diary-app

6. 环境变量配置

在Travis CI中设置以下环境变量:

  • HEROKU_API_KEY: Heroku API密钥
  • MONGODB_PROD_URI: 生产环境MongoDB连接字符串(使用MongoDB Atlas或Heroku Add-on)

在Heroku中设置:

heroku config:set MONGODB_URI=your_mongodb_atlas_uri

7. go.mod 依赖

module my-diary-app

go 1.19

require (
    go.mongodb.org/mongo-driver v1.11.0
)

这个配置实现了完整的CI/CD流程:代码推送到GitHub → Travis CI运行单元测试(包括MongoDB测试)→ 测试通过后自动部署到Heroku → Heroku使用配置的MongoDB URI启动应用。

回到顶部