1

当我尝试使用 CodeBuild golang image 1.10 构建我的 golang 项目时,它失败了,无法找到子包。一些背景:

该应用程序的组织如下:

/go/src/company/app
/go/src/company/app/sub1
/go/src/company/app/sub2
etc...

这在我的开发机器上运行良好。但是,当被 codebuild 拉取时,它会被拉入不同的目录 ( /codebuild/output/srcNNN/src/<some path>),其中<some path>根据触发构建的内容而有所不同。

我最初是通过将代码从拉到 golang 目录 ( /codebuild/output/srcNNN) 的位置复制代码来使其工作的,但是由于目录的 CodeBuild 环境变量在前面GOPATH插入 /go: ( /go:/codebuild/output/srcNNN),因此我使用了观察到的 ../ ../... 复印。但是,一旦我以不同的方式触发构建,这很丑陋并且失败了。

我的问题是是否有一个好方法可以让这个工作?我的下一个想法是将字符串操作应用于观察到的路径并复制到那里以获得(希望)更高的可靠性。但这只有在GOPATH符合我的假设的情况下才有效。

任何想法,将不胜感激。


澄清:在代码中导入包时,外部包的导入方式如下:

import (
    "context"
    ...
}

子包不是显式导入的,而是在部署代码时发现的,如上所示 ( /go/src/company/app)。但是,AWS CodeBuild 不会以这种方式引入代码。

4

2 回答 2

3

如果您使用的是 golang 1.11 或更高版本,请参阅下面的更新以获得完整的答案......我们不再使用我最初的工作。

我能够得到一个有效的答案。我会把它贴在这里以防它对其他人有帮助,但它依赖于 AWS CodeBuild 中观察到的行为才能工作,所以我认为它并不理想。

在我的 buildspec.yaml 中,我可以通过以下方式使构建工作:

  1. ${THEGOPATH}从开头${GOPATH}删除“/go:”
  2. 将所有代码复制到${THEGOPATH}/src/<app path>
  3. 将其他存储库复制到${THEGOPATH}/src/<other app path>
  4. 正常导入外部依赖项(在我们的例子中,go get ./...或显式)
  5. 构建和强制输出名称(从 CodeBuild 启动时,它使用不同的目录名称)

buildspec.yaml 类似于以下内容:

phases:
  install:
    commands:
      - echo GOPATH - $GOPATH
      - export THEGOPATH=`echo $GOPATH | cut -c 5-`
      - echo THEGOPATH = $THEGOPATH
      - mkdir -p ${THEGOPATH}/src/company/app1
      - mkdir -p  ${THEGOPATH}/src/company/other_repository_dependency
      - echo Copy source files to go root
      - cp -a ${CODEBUILD_SRC_DIR}/. ${THEGOPATH}/src/company/app1/${PACKAGE}
      - cp -a ${CODEBUILD_SRC_DIR_other_dep}/. ${THEGOPATH}/src/app/other_repository_dependecy/.
      - ls ${THEGOPATH}/src/
  build:
    commands:
      - echo Build started on `date`
      - echo Getting packages
      - go get ./...
      - echo DOING THE BUILD
      - go build -ldflags "<some flags>" -o "appname"
      - go test ./...
  post_build:
    commands:
      - echo Build completed on `date`
      - ls -al
      - pwd
artifacts:
  files:
    - appname

更新——更好的修复 今天我们尝试使用 go 模块(从 1.11 开始可用)构建,请参阅此处了解 go 模块的说明。

company-name.com使用 go 模块,我们在 go.mod 文件中定义了当前源模块 app1,如下所示:

module company-name.com/app1

go 1.12
require (
   ... *for example*
   github.com/golang/mock v1.3.1
   github.com/google/btree v1.0.0 // indirect
   github.com/google/go-cmp v0.3.0
   ... *etc*

我们甚至以这种方式引用我们的外部文件(尽管您需要弄清楚如何使用您的 git 存储库进行身份验证。我们使用构建规范中内置的凭证助手进行 https 身份验证)。所以,我们的导入块现在看起来像这样:

     import ( 
       "company-name.com/app1/subpackage1"
       abbrev "company-name.com/app1/subpackage2"
       "company-name.com/externalpkg"  // In another private git repo of ours
       ... //etc
     )
     ... //golang source follows here*

最后,我们在 buildspec 中添加了以下环境变量:

  variables:
    GO111MODULE: "on"
    git-credential-helper: yes

这些确保了模块在路径中工作(感谢 amwill04 提醒我我的遗漏)并允许我们的 Git 存储库的凭据正确设置。

在这样做的过程中,我们完成了我们需要的一切:

  1. 通过更改对 go 模块的引用,我们可以轻松地引用子包
  2. 我们能够锁定所有依赖项的版本
  3. 通过在 company-name.com 上实现一个简单的服务器,我们可以从我们的应用程序中引用其他私有模块
于 2018-11-20T17:09:03.423 回答
1

这是我采取的方法。

version: 0.2

env:
  variables:
    PACKAGE: "github.com/rhyselsmore/foo"

phases:
  install:
    commands:
      # AWS Codebuild Go images use /go for the $GOPATH so let's copy our
      # application source code into that directory structure.
      - mkdir -p "/go/src/$(dirname ${PACKAGE})"
      - ln -s "${CODEBUILD_SRC_DIR}" "/go/src/${PACKAGE}"
      - # Make sure we're in the package directort within our GOPATH
      - cd "/go/src/${PACKAGE}"

现在假设 PACKAGE 变量是您正在构建的存储库的根目录,我们可以发出 go 命令。让我们逐行分解。

- mkdir -p "/go/src/$(dirname ${PACKAGE})"

这会在 GOPATH 中为您的包创建一个新目录。

- ln -s "${CODEBUILD_SRC_DIR}" "/go/src/${PACKAGE}"

这会创建一个从 CodeBuild 项目的根目录到 Go 包的符号链接。

- cd "/go/src/${PACKAGE}"

这将准备好其余的 Codebuild 操作,以在 Go 包的 CWD 中进行。

于 2019-06-07T01:08:17.950 回答