Golang私人模块与CDK CodeBuild
#aws #serverless #go #cdk

即使有经验的建筑商也会不时遇到他们以前从未见过的事物,这会给他们带来麻烦。我已经与CDKCodePipeline,CodeBuild和Golang合作了几年,并且不需要构建一个私人的Golang模块。几周前,情况发生了变化,这使我震惊,因为我还需要将其包含在CodeBuild步骤中的代码上。本文是未来的文档和参考,因为我想与CodeBuild分享用于构建Golang私有模块的模式。

解决方案图

供参考,这是解决方案图,我将在整个文章中引用。对于基础架构,我将使用CDK与Typescript。

Building Golang private modules CodeBuild

管道

让我们漫步在codepipeline上,该码头将负责从GitHub接收更改,然后运行构建和部署。

export class PipelineStack extends cdk.Stack {
    constructor(scope: Construct, id: string) {
        super(scope, id);

        const pipeline = new CodePipeline(this, "Pipeline", {
            pipelineName: "SamplePipeline",
            dockerEnabledForSynth: true,
            synth: new CodeBuildStep("Synth", {
                input: CodePipelineSource.gitHub(
                    "benbpyle/cdk-step-functions-local-testing",
                    "main",
                    {
                        authentication: SecretValue.secretsManager(
                            "sf-sample",
                            {
                                jsonField: "github",
                            }
                        ),
                    }
                ),

                buildEnvironment: {
                    buildImage: LinuxBuildImage.STANDARD_6_0,
                    environmentVariables: {
                        GITHUB_USERNAME: {
                            value: "benbpyle",
                            type: BuildEnvironmentVariableType.PLAINTEXT,
                        },
                        GITHUB_TOKEN: {
                            value: "sf-sample:github",
                            type: BuildEnvironmentVariableType.SECRETS_MANAGER,
                        },
                    },
                },
                partialBuildSpec: BuildSpec.fromObject({
                    phases: {
                        install: {
                            "runtime-versions": {
                                golang: "1.18",
                            },
                        },
                    },
                }),

                commands: [
                    'echo "machine github.com login $GITHUB_USERNAME password $GITHUB_TOKEN" >> ~/.netrc',
                    "npm i",
                    "export GOPRIVATE=github.com/benbpyle",
                    "npx cdk synth",
                ],
            }),
        });

        pipeline.addStage(new PipelineAppStage(this, `Deploy`, {}));
    }
}

我想分解其中的一些组件。

源动作

我正在使用GitHub源和SecretsManager来存储个人访问令牌,该令牌将处理更改并将源拉入代码构造步骤

input: CodePipelineSource.gitHub(
    "benbpyle/cdk-step-functions-local-testing",
    "main",
    {
        authentication: SecretValue.secretsManager(
            "sf-sample",
            {
                jsonField: "github",
            }
        ),
    }
),

建立步骤

构建步骤还需要访问SecretsManager。我将在下面的commands块中解释。构建环境使我能够设置构建图像,然后设置环境变量。通过使用SecretsManager,我可以将隐藏的访问令牌隐藏起来,但可以在构建中访问它。 CodeBuild在掩盖*****的值中也做得很好,如果您尝试将其echo算出来。

buildEnvironment: {
    buildImage: LinuxBuildImage.STANDARD_6_0,
    environmentVariables: {
        GITHUB_USERNAME: {
            value: "benbpyle",
            type: BuildEnvironmentVariableType.PLAINTEXT,
        },
        GITHUB_TOKEN: {
            value: "sf-sample:github",
            type: BuildEnvironmentVariableType.SECRETS_MANAGER,
        },
    },
},

构建命令

这种模式的症结在于,我正在使用~/.netrc文件存储我的github pat,以登录Golang从Github提出的命令时进行登录。有关~/.netrc的更多信息,这是指向GNU的链接。并阅读Golang Modules的工作原理

commands: [
    'echo "machine github.com login $GITHUB_USERNAME password $GITHUB_TOKEN" >> ~/.netrc',
    "npm i",
    "export GOPRIVATE=github.com/benbpyle",
    "npx cdk synth",
],

npx cdk synth命令运行时,会发现堆栈中有一个Golang函数,并且将执行go mod tidy,从而从依赖项中启动拉动。另一个关键部分是,我要设置$GOPRIVATE环境变量,该变量告诉您​​不使用公共软件包注册表并从这些特定位置提取软件包。该变量可以是顶级路径,也可以是逗号分隔的列表。 An article描述了它在发行几个Golang版本时的用法。

部署

在此示例中,我已经部署了一个单个阶段,但是在生产用例中,您将拥有开发,测试,预生产,产品,产品等环境。

// The stage
export class PipelineAppStage extends cdk.Stage {
    constructor(scope: Construct, id: string, props: cdk.StageProps) {
        super(scope, id, props);

        new MainStack(this, `App`, {});
    }
}

// MainStack
export class MainStack extends cdk.Stack {
    constructor(scope: Construct, id: string, props: cdk.StackProps) {
        super(scope, id, props);

        new ExampleFunc(this, "ExampleFunc");
    }
}

// Function Definition
export class ExampleFunc extends Construct {
    constructor(scope: Construct, id: string) {
        super(scope, id);

        new GoFunction(scope, `ExampleFuncHandler`, {
            entry: path.join(__dirname, `../../../src/example-func`),
            functionName: `example-func`,
            timeout: Duration.seconds(30),
            bundling: {
                goBuildFlags: ['-ldflags "-s -w"'],
            },
        });
    }
}

在这里讨论不多,但是您可以看到:

的定义
  • appstage
  • mainstack
  • examplefunc

将所有内容融合在一起,将舞台添加到管道

pipeline.addStage(new PipelineAppStage(this, `Deploy`, {}));

用CodeBuild构建Golang私人模块

golang利用一个go.mod文件和一个存储这些依赖关系的依赖项,版本和校验和的go.sum文件。如果您的代码直接导入某些内容或您的代码导入具有该依赖关系,则您还列出了直接和间接的依赖关系。

此示例的go.mod文件看起来像这样。

我对

有依赖性
  • 是的
  • Sirupsen(Logus)
  • 我的个人私人图书馆
module example

go 1.18

require (
    github.com/aws/aws-lambda-go v1.40.0
    github.com/sirupsen/logrus v1.9.0
)

require (
    github.com/benbpyle/golang-private-sample v0.0.0-20230506132255-dc7062e24dff
    github.com/stretchr/testify v1.8.2
    golang.org/x/sys v0.7.0
)

和处理程序代码引用了go.mod文件中的那些东西,只是打印出消息

package main

import (
    "context"

    "github.com/aws/aws-lambda-go/lambda"
    s "github.com/benbpyle/golang-private-sample"
    "github.com/sirupsen/logrus"
)

func main() {
    lambda.Start(handler)
}

func handler(ctx context.Context, event interface{}) error {
    logrus.Info("Logging out the handler")

    s.TestMe("the handler")

    return nil
}

包起来

将所有这些放在一起将使您有能力在您的golang模块中拥有一定程度的隐私。当使用CodeBuild构建Golang Private模块时,您可以通过CDK,Terraform或本地云形式轻松地将其包含在管道中。如果您使用的是另一个CI/CD执行框架,则此方法也将起作用。

与往常一样,本文的源代码可在GitHub上找到。随意克隆并尝试一下。但是请注意,您无法访问以下内容。

  • 用您的私人存储库
  • 替换我的私人存储库
  • sf-sample秘密是我创建的,您需要创建自己的

享受快乐建筑!