---
# System prepended metadata

title: ops-staging 環境建置

---

# ops-staging 環境建置
## 前置準備
* 下載 protoc [檔案 ( win64 )](https://github.com/protocolbuffers/protobuf/releases/download/v21.5/protoc-21.5-win64.zip) 

* 將 protoc 解壓縮後的檔案放到 `GOPATH` 底下，或是定義於環境變數中 [參考作法(1)](https://medium.com/hamielkuo/go-grpc-protobuf-gogo%E5%AE%89%E8%A3%9D%E7%AD%86%E8%A8%98-d2f66342bc8) [參考作法(2)](https://www.geeksforgeeks.org/how-to-install-protocol-buffers-on-windows/)
* https://ithelp.ithome.com.tw/articles/10250131

    ![](https://i.imgur.com/d0Od3HA.png)


* 安裝 minGW ( 用於 Makefile ) [安裝教學](https://www.ics.uci.edu/~pattis/common/handouts/mingweclipse/mingw.html)

* 安裝 protoc 相關套件

    ```cmd
    go get -u github.com/golang/protobuf/protoc-gen-go
    go get github.com/gogo/protobuf/protoc-gen-gofast
    go get github.com/gogo/protobuf/protoc-gen-gogoslick
    ```
* 切換不同版本的 Go [官方說明](https://go.dev/doc/manage-install)、[其他教學](https://babygoat.github.io/2019/06/19/Golang-mac%E4%B8%8A%E5%88%87%E6%8F%9B%E5%A4%9A%E5%80%8Bgo%E7%89%88%E6%9C%AC/)

    ```cmd
    go get golang.org/dl/go1.19.1
    go1.19.1 download
    ```
    輸入指令時，將所有的 `go` 換成 `go1.19.1` 即可切換到新版本
---

## 專案生成
* 前往存放專案的目錄下

    ```cmd
    go install github.com/go-kratos/kratos/cmd/kratos/v2@latest
    ```
    1.  建立一個名為 `helloworld` 的專案

        ```cmd
        kratos new helloworld -r http://10.40.41.72/DevOps/ops-staging.git
        ```

    2. Download 執行時間較長，會花數分鐘
        ```cmd
        make download
        ```
    
    3. 使用 **git bash** 執行 `make proto` ( [參考來源](https://www.gnu.org/software/make/manual/html_node/Choosing-the-Shell.html) )
        ```cmd
        make proto
        ```
        或者是在原先外層目錄下執行 ( 在此使用 `hello.proto` 作為名稱)
        ```cmd
        kratos proto client --proto_path=./proto api//example/v1/hello.proto;
        ```
        
        :::spoiler *其他補充*
        `make proto` 可能會缺少部分引用套件，可以從 [這裡](https://fuchsia.googlesource.com/third_party/googleapis/) 下載 Google API 第三方套件 ( [StackOverflow 討論](https://stackoverflow.com/questions/66168350/import-google-api-annotations-proto-was-not-found-or-had-errors-how-do-i-add) )。或是 cd 到 `/api` 目錄下再執行 `make proto`
        :::
    4. 安裝 air
        ```cmd
        go get -u github.com/cosmtrek/air
        ```
    
    5. 產生 exe 執行檔
        ```cmd
        make build
        ```
---
## 開發方式

### 1. 前置定義
* 定義 gRPC 之 Proto Buffer

    ```cmd
    路徑：api\{$SERVICE_NAME}\{$MODULE_NAME}\{$VERSION}
    例如：api\component\sonarqube\v1
    ```
* 定義接口入參以及回參的規格
    * 在上述路徑下建立 `.proto` 檔案


        ```go
        // 定義 proto 版本，一般皆為 proto3
        syntax = "proto3";
        
        // proto package 路徑
        package api.component.sonarqube.v1;

        // proto package 路徑
        option go_package = "component-service/api/component/sonarqube/v1;v1";

        // 定義 rpc 服務
        service Sonarqube {
          rpc GetSonarqube (GetSonarqubeRequest)returns(GetSonarqubeReply);
          rpc GetSonarqubeList (GetSonarqubeListRequest)returns(GetSonarqubeListReply);
        }

        // 入參
        message GetSonarqubeRequest {
          int32 ID = 1;
          string Department = 2;
          string Url = 3;
          string Account = 4;
          string Pass = 5;
        }
        
        // 回參
        message GetSonarqubeReply {
          string Msg = 1;
        }

        // ------------------------------

        // 入參
        message GetSonarqubeListRequest {
          int32 ID = 1;
          string Department = 2;
          string Url = 3;
          string Account = 4;
          string Pass = 5;
        }

        // 回參 (多筆資料)
        // 回傳一個 List (陣列) 以及資料數量 (int64)
        message GetSonarqubeListReply {
          message SonarqubeList {
            int32 ID = 1;
            string Department = 2;
            string Url = 3;
            string Account = 4;
            string Pass = 5;
          }
          // 使用 repeated 為回傳陣列的表示方式
          repeated SonarqubeList sonarqube_list = 1;
          int64 total = 2;
        }
        ```
    * 定義完成後，在專案根目錄執行 `make proto` 生成 `.go` 檔案。

### 2. 編譯方式
* 路徑為 `cmd/{$MODULE_NAME}`，在 Goland 右鍵 **RUN** 即可編譯並執行本專案。

    ![](https://i.imgur.com/RzfjP5G.png)
* 效果等同：

    ```cmd
    go build {$PROJECT_NAME}/cmd/{$MODULE_NAME}
    ``` 
    
### 3. 打包推送
* 目前 drone 無法使用，因此採手動打包至 Harbor。
    
    * 上 [Harbor](https://registry.digiwincloud.com/harbor/sign-in) 檢查專案版本號，在此以 `ops/component-service` 為例：

    ![](https://i.imgur.com/rYJ4qoS.png)

* 由於 `sonar-go sdk` 位於 `10.40.41.72` 私有庫，在 docker build 的 **make download** 步驟中有機會出錯，因此我們要修改專案中的 `Makefile`。
    * 加入 49-53 行至 `Makefile`

        ```makefile=47
        download:
        @go env -w GOPROXY=https://goproxy.cn,direct,http://10.40.41.72; \
        go env -w GOPRIVATE=10.40.41.72
        go env -w GOINSECURE=10.40.41.72
        git config --global url."http://fe8edb59768a3b3b03bf9894836c9a1ada8757ed:x-oauth-basic@10.40.41.72".insteadOf "http://10.40.41.72"
        git config --global user.email "robot@digiwin.com"
        git config --global user.name "drone"
        go mod download; \
        ```
    * 在專案內執行 docker build 
        ```cmd
        docker build -t registry.digiwincloud.com/ops/component-service:5.2.0.100X
        ```
    * 推送至 Harbor 
        ```cmd
        docker push registry.digiwincloud.com/ops/component-service:5.2.0.100X
        ```

---    
## 其他補充
* 程式碼不在 GOROOT 之報錯
    * 通常都是抓不到 `api/{$NAME}/v1`，只需使用 **git bash** 在專案根目錄執行 `make proto` 就可解決
    <br>
    ```cmd
    make proto
    ```

    
* 以 [BloomPRC](https://github.com/bloomrpc/bloomrpc) 測試

    教學參考：https://pjchender.dev/golang/grpc-getting-started/#%E5%AF%A6%E4%BD%9C-grpc-server
    
*  產生 ent 相關程式碼

    ```cmd
    D:\devops_kratos\helloworld\internal\app\component\ent> go generate ./...
    ```
    
* Git Submodule 相關操作 [[ 連結 ]](https://devconnected.com/how-to-add-and-update-git-submodules/)
    
    1. `api` 目錄採用 Git Submodule 方式開發，裡面有各模組的 `proto` 檔。
    2. 新增 `api` submodule
        ```cmd
        # 新增 submodule
        git submodule add http://10.40.41.72/DevOps/api.git
        
        # commit 後生效
        git commit -m "Added submodule"
        
        git push        
        ```

    2. 若要更新 `api`，檢查專案目錄下是否有 `.gitmodules`，再執行
        ```cmd
        git submodule update --init --recursive
        ```