如何在AWS上使用子模块自动部署git存储库?

var*_*yar 11 git github git-submodules aws-code-deploy

我的git存储库中有一个子模块,我的目录结构是这样的,

app
  -- folder1
  -- folder2
  -- submodule @5855
Run Code Online (Sandbox Code Playgroud)

我已使用autodeploy服务在AWS上部署了我的代码.现在,在服务器上,我在父目录中有代码,但子模块目录是空的.

Q1)如何在子模块中获取数据.我在服务器上的存储库不是git存储库.我是否需要先将其转换为git repo,然后运行submodule命令才能获得它?

Q2)如何自动化子模块部署?

谢谢

Mat*_*cci 11

我明天会清理这个答案,但这对我有用

我们将重新初始化git存储库,然后在部署的构建阶段触发子模块克隆,基本上修补了对codepipeline/codebuild中的子模块的支持

  • 如果使用您可能想要创建部署用户的组织,请为您的github帐户生成新的SSH密钥
  • aws ssm put-parameter --name build_ssh_key --type String --value "$(cat id_rsa)"使用SecureString而不是String 将这个ssh密钥存储在你的aws参数存储中,但是我之后的指南只是使用了字符串,所以我不确定命令行是否需要任何额外的参数,明天将测试
  • 进入IAM并授予您的CodePipeline用户对您的paramstore的读取权限,我只是授予了对SSM的读取权限

然后使您的buildspec.yml看起来如下所示:

version: 0.2

env:
  parameter-store:
    build_ssh_key: "build_ssh_key"

phases:
  install:
    commands:
      - mkdir -p ~/.ssh
      - echo "$build_ssh_key" > ~/.ssh/id_rsa
      - chmod 600 ~/.ssh/id_rsa
      - ssh-keygen -F github.com || ssh-keyscan github.com >>~/.ssh/known_hosts
      - git config --global url."git@github.com:".insteadOf "https://github.com/"
      - git init
      - git remote add origin <Your Repo url here using the git protocol>
      - git fetch
      - git checkout -t origin/master
      - git submodule init
      - git submodule update --recursive
  build:
    commands:
      - echo '...replace with real build commands...'

artifacts:
  files:
    - '**/*'
Run Code Online (Sandbox Code Playgroud)

  • 当我们不能使用子模块时,这个 aws CodeCommit 真的很垃圾。我想我只会制作一个批处理脚本,它比这个非工作 CI/CD“工具”要容易得多 (2认同)

Dou*_*ton 8

经过一整天的努力,我找到了一个简单的解决方案(用于代码管道),它不需要在 buildspec 中处理任何 SSH 密钥。我正在使用 Bitbucket,但我认为这适用于其他提供商。我也在通过 https 克隆我的子模块,我不确定这是否是一个要求。

  1. 配置您的源以执行存储库的完整克隆。这将传递您需要的 git 元数据。 源码配置

  2. 配置您的构建角色以添加客户管理的 UseConnection 权限,以授予您的构建操作访问您为源配置的凭据的权限。来自 AWS 的文档:https : //docs.aws.amazon.com/codepipeline/latest/userguide/troubleshooting.html#codebuild-role-connections

  3. 设置您的 env 以包含git-credential-helper: yes并在 buildspec.yml 中克隆子模块:

在此处输入图片说明

就是这样!子模块将可用于构建,而无需为您要使用的每个子模块进行大量关键配置。

如果这最终对人们有用,也许是对文档的一个很好的补充。

  • 这实际上是有效的,对于使用 CodePipeline 的用户,您需要执行以下操作:转到 CodeBuild 项目,编辑,源,添加新源,选择 Github,通过 Oauth 或个人访问令牌连接,设置存储库,然后保存(您可以稍后删除源)您需要的是在 CODEBUILD 中创建连接,而不是 CodePipeline。这将在 CodeBuild 容器中启用凭证助手。您可以通过检查构建日志进行调试,在“Git credential helperenabled”下方您不应该看到:GITHUB Git credential unavailable。或者 BITBUCKET(如果是这样的话)。希望这对某人有帮助。 (4认同)

Jos*_*ans 6

我自己遇到了这个问题,并且由于@ matt-bucci的出色建议,我得以提出一个看似健壮的解决方案。

我的特定用例略有不同-我使用Lambda层来减少lambda冗余,但仍需要将这些层作为子模块包含在Lambda函数存储库中,以便CodeBuild可以构建和测试PR。我使用CodePipeline来协助持续交付-因此我需要一个本身可以同时使用CodePipeline和CodeBuild的系统

  1. 按照这些说明,我创建了一个新的SSH密钥,供“机器用户” 使用。在这种情况下,我使用的是计算机用户,因此不需要为每个项目都生成新的ssh密钥,也不需要为多个私有子模块提供潜在的支持

  2. 我将私钥作为SecureString存储在AWS Parameter Store中。这实际上并没有改变CodeBuild中的任何内容,因为它足够聪明,只知道如何解密密钥

  3. 我给了“ codebuild”角色AWS托管属性:AmazonSSMReadOnlyAccess-允许CodeBuild访问私钥

  4. 我使用@ matt-bucci建议的一堆命令以及一些新命令创建了buildspec.yml文件。

# This example buildspec will enable submodules for CodeBuild projects that are both 
# triggered directly and via CodePipeline
#
# This buildspec is designed with help from Stack Overflow: 
# /sf/ask/2989877971/
version: 0.2  # Always use version 2
env:
  variables:
    # The remote origin that will be used if building through CodePipeline
    remote_origin: "git@github.com:your/gitUri"
  parameter-store:
    # The SSH RSA Key used by our machine user
    ssh_key: "ssh_key_name_goes_here"
phases:
  install:
    commands:
      # Add the "machine user's" ssh key and activate it - this allows us to get private (sub) repositories
      - mkdir -p ~/.ssh                   # Ensure the .ssh directory exists
      - echo "$ssh_key" > ~/.ssh/ssh_key  # Save the machine user's private key
      - chmod 600 ~/.ssh/ssh_key          # Adjust the private key permissions (avoids a critical error)
      - eval "$(ssh-agent -s)"            # Initialize the ssh agent
      - ssh-add ~/.ssh/ssh_key            # Add the machine user's key to the ssh "keychain"
      # SSH Credentials have been set up. Check for a .git directory to determine if we need to set up our git package
      - |
        if [ ! -d ".git" ]; then
          git init                                              # Initialize Git
          git remote add origin "$remote_origin"                # Add the remote origin so we can fetch
          git fetch                                             # Get all the things
          git checkout -f "$CODEBUILD_RESOLVED_SOURCE_VERSION"  # Checkout the specific commit we are building
        fi
      # Now that setup is complete, get submodules
      - git submodule init
      - git submodule update --recursive
      # Additional install steps... (npm install, etc)
  build:
    commands:
      # Build commands...
artifacts:
  files:
    # Artifact Definitions...
Run Code Online (Sandbox Code Playgroud)

该安装脚本执行三个独立的步骤

  1. 它安装并启用用于访问私有存储库的ssh私有密钥

  2. 它确定是否存在.git文件夹-如果没有,则脚本将初始化git并检出正在构建的确切提交。注意:根据AWS文档,$CODEBUILD_RESOLVED_SOURCE_VERSIONenvar不保证存在于CodePipeline构建中。但是,我没有看到这个失败

  3. 最后,它实际上获得了子模块

显然,这不是解决此问题的好方法。但是,鉴于CodePipeline的(不必要)限制,这是我能想到的最好的方法。此过程的副作用是“源” CodePipeline阶段是完全不值钱的,因为我们只是覆盖已归档的源文件-它仅用于侦听存储库的更改

两年来,人们一直要求更好的功能:https : //forums.aws.amazon.com/thread.jspa?threadID=248267

编辑于2019年1月23日

我意识到(艰难的方式)我以前的响应不支持CodePipeline构建,仅直接通过CodeBuild运行。当CodeBuild响应GitHub Webhook时,它将克隆整个GitHub存储库,包括.git文件夹

但是,当使用CodePipeline时,“源”操作将克隆存储库,签出相应的分支,然后在不带 .git文件夹的情况下处理原始文件。这意味着我们必须初始化github存储库才能访问子模块


Kus*_*era 6

我在AWS CodeBuild上遇到了同样的问题。我Use Git submodules像下图一样勾选以更新我的submodule.

在此输入图像描述

当我运行构建时出现以下错误,

CLIENT_ERROR: Submodule error error creating SSH agent: "SSH agent requested but SSH_AUTH_SOCK not-specified" for primary source and source version refs/heads/dev
Run Code Online (Sandbox Code Playgroud)

因此,我在 google 上搜索了上述错误,并从 AWS 论坛得到了DOWNLOAD_SOURCE Fails with Git submodules线程。他们提到过,

子模块必须配置为 https 而不是 ssh。

我认为这没什么用,有人设置submodule为会发生什么ssh。我也做了同样的事情,这是我的.gitmodules文件。

[submodule "common"]
    path = common
    url = git@bitbucket.org:organization_id/common.git
Run Code Online (Sandbox Code Playgroud)

真的,我不想把它改成https。然后我在媒体上找到了这篇Working with Git Submodules in CodePipeline文章。我想想象一下我为解决此问题所做的工作,并且存在该文章中未提及的错误。让我们以更安全的方式做到这一点。


首先转到AWS Key Management Service (KMS),然后转到Customer managed keys部分并单击Create key创建密钥。

  1. 单击Symmetric,然后单击Next

在此输入图像描述

  1. 提供任意名称(例如:- bitbucket-credentials)来创建Alias并单击Next

在此输入图像描述

  1. 您很可能已经可以在 AWS 上AWS Role配置任何开发人员工具,因此在我的例子中,我创建了对AWS CodeBuild 的调用,并为其提供了 并单击。AWS RoleecsCodeBuildRoleDefine key administrative permissionsNext

在此输入图像描述

  1. 接下来给出Define key usage permissions您的AWS Role并单击Next

在此输入图像描述

  1. 最后检查您到目前为止所做的事情并单击Finish以创建CMK

在此输入图像描述

  1. 您可以像下面这样查看它。

在此输入图像描述


AWS Key Management Service (KMS)部分已完成,现在转到AWS Systems Manager并找到该Parameter Store部分。点击Create parameter

  1. 只需将其命名为id_rsa并放置与下面相同的内容即可。

在此输入图像描述 在此输入图像描述

  1. 对于本value部分,只需cat ~/.ssh/id_rsa在终端中运行命令,您将获得如下所示的输出。将其添加到该value部分。
-----BEGIN RSA PRIVATE KEY-----
qdjbXp+42VTnccC7pxOZcofomfwGXPWuqcv99sQEPtToODvGIxWoooJUpb6qMIWY
1zccEuwAhmqcPvpsJyWhcctZB/wWglNvViZcOYjrQ8HBUBKJT8pF
-----END RSA PRIVATE KEY-----
Run Code Online (Sandbox Code Playgroud)
  1. 创建另一个参数并将其命名为id_rsa.pub。按照与上面相同的步骤进行操作。

  2. 对于本value部分,只需cat ~/.ssh/id_rsa.pub在终端中运行命令,您将获得如下所示的输出。将其添加到该value部分。

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGtf8jjkogWxRGNGjJlOZ1G+pWExgDOdA5wVML6TMTT2YtvhPJD60nPx5TfA8zRzGWubwrPp40SPAhSs5wiAAg38HlS4pz9X wasdkiller@wasdkiller
Run Code Online (Sandbox Code Playgroud)

根据我的研究(也许我错了,请纠正我),我没有任何其他方法可以在不付出这么多努力的情况下将ssh凭证传递给AWS CodeBuild 。所以我buildspec.yml像这样手动更改了我的文件。

version: 0.2

env:
  parameter-store:
    ssh_key: id_rsa
    ssh_pub: id_rsa.pub

phases:
  install:
    commands:
      - mkdir -p ~/.ssh
      - echo "$ssh_key" > ~/.ssh/id_rsa   
      - echo "$ssh_pub" > ~/.ssh/id_rsa.pub
      - chmod 600 ~/.ssh/id_rsa
      - eval "$(ssh-agent -s)"
      - git submodule update --init --recursive
Run Code Online (Sandbox Code Playgroud)

当你继续时,你肯定会得到以下错误,

version: 0.2

env:
  parameter-store:
    ssh_key: id_rsa
    ssh_pub: id_rsa.pub

phases:
  install:
    commands:
      - mkdir -p ~/.ssh
      - echo "$ssh_key" > ~/.ssh/id_rsa   
      - echo "$ssh_pub" > ~/.ssh/id_rsa.pub
      - chmod 600 ~/.ssh/id_rsa
      - eval "$(ssh-agent -s)"
      - git submodule update --init --recursive
Run Code Online (Sandbox Code Playgroud)

它会询问您的ssm:GetParameters权限,只需附加AmazonSSMReadOnlyAccess策略或使用权限手动创建策略ssm:GetParameters并将其附加到您的AWS Role,它就会解决这个问题。

  • 感谢这个,它工作得很好 - 我还必须添加 `- ssh-keygen -F github.com || ssh-keyscan github.com &gt;&gt;~/.ssh/known_hosts` 以使其连接到 github 存储库。干杯 (3认同)

Mar*_*nde 5

虽然@MattBucci 的回答有效,但需要注意的是,您只能拉取特定分支,而不能拉取子模块正在使用的特定提交。

为了处理这种情况,这在使用子模块时很可能发生,需要做很多事情:

1)创建一个gitpre-commit钩子,内容如下:

#!/bin/bash

#   This file is used in post-commit hook
#   if .commit exists you know a commit has just taken place but a post-commit hasn't run yet
#
touch .commit
Run Code Online (Sandbox Code Playgroud)

如果您已经有了,可以在开头添加该行。

2)post-commit使用以下内容创建一个 git钩子:

#!/bin/bash


DIR=$(git rev-parse --show-toplevel);

if [[ -e $DIR/.commit ]]; then
    echo "Generating submodule integrity file"
    rm .commit

    SUBMODULE_TRACKING_FILE=$DIR/.submodule-hash
    MODULE_DIR=module
    #   Get submodule hash, this will be used by AWS Code Build to pull the correct version.
    #   AWS Code Build does not support git submodules at the moment
    #   https://forums.aws.amazon.com/thread.jspa?messageID=764680#764680
    git ls-tree $(git symbolic-ref --short HEAD) $MODULE_DIR/ | awk '{ print $3 }' > $SUBMODULE_TRACKING_FILE

    git add $SUBMODULE_TRACKING_FILE
    git commit --amend -C HEAD --no-verify
fi

exit 0
Run Code Online (Sandbox Code Playgroud)

这个钩子会将当前提交的哈希放入.submodule-hash文件中,这个文件需要提交给版本控制

3)转到您的 AWS 代码构建项目

Developer Tools > CodeBuild > Build projects > YOUR_PROJECT > Edit Environment
Run Code Online (Sandbox Code Playgroud)

添加一个名为: 的环境变量GIT_KEY,该值将是 64 位编码的 ssh 密钥。(没有换行符,否则将无法工作)。

您可以在线转换它,或使用任何工具或编程语言。

在此处输入图片说明

4)在你buildspec.yml添加一个pre_build脚本。

version: 0.2

phases:
  pre_build:
    commands:
      - bash build/aws-pre-build.sh
...
Run Code Online (Sandbox Code Playgroud)

5)build/aws-pre-build.sh使用以下内容创建:

Developer Tools > CodeBuild > Build projects > YOUR_PROJECT > Edit Environment
Run Code Online (Sandbox Code Playgroud)

附加功能

如果在转到 AWS 代码构建之前有一个额外的步骤,例如 bitbucket 管道或类似的东西,您可以检查实际的 git 子模块哈希是否与生成的文件中的哈希匹配:.submodule-hash.

如果它不匹配,则意味着曾经推送过的人没有 git 钩子。

version: 0.2

phases:
  pre_build:
    commands:
      - bash build/aws-pre-build.sh
...
Run Code Online (Sandbox Code Playgroud)

注意:您还可以在 AWS Code Build 之前在管道上创建该文件、创建提交、标记并推送它,以便 AWS Code Build 管道开始。

#!/bin/bash

set -e

#   Get root path
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )"

MODULE_HASH=$(cat $DIR/.submodule-hash);
GIT_HOST=bitbucket.org
MODULE_DIR=module
REPO=user/repo.git


if [[ ! -d ~/.ssh ]]; then
    mkdir ~/.ssh
fi

if [[ ! -f ~/.ssh/known_hosts ]]; then
    touch ~/.ssh/known_hosts
fi

#   Base64 decode private key, and save it to ~/.ssh/git
echo "- Adding git private key"

echo $GIT_KEY | base64 -d > ~/.ssh/git

#   Add correct permissions to key
chmod 600 ~/.ssh/git

#   Add $GIT_HOST to ssh config
echo "- Adding ssh config file"

cat > ~/.ssh/config <<_EOF_
Host $GIT_HOST
    User git
    IdentityFile ~/.ssh/git
    IdentitiesOnly yes
_EOF_

#   Check if host is present in known_hosts
echo "- Checking $GIT_HOST in known_hosts"

if ! ssh-keygen -F $GIT_HOST > /dev/null; then
    echo "- Adding $GIT_HOST to known hosts"
    ssh-keyscan -t rsa $GIT_HOST >> ~/.ssh/known_hosts
fi

#   AWS Code build does not send submodules, remove the empty folder
rm -rf $MODULE_DIR

# Clone submodule in the right folder
git clone git@$GIT_HOST:$REPO $MODULE_DIR

# cd to submodule
cd $DIR/$MODULE_DIR

# Checkout the right commit
echo "- Checking out $MODULE_HASH"

git checkout $MODULE_HASH

Run Code Online (Sandbox Code Playgroud)