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

问题描述 投票:10回答:4

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

app
  -- folder1
  -- folder2
  -- submodule @5855

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

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

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

谢谢

git github git-submodules aws-code-deploy
4个回答
10
投票

这对我有用

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

  • 如果使用您可能想要创建部署用户的组织,请为您的github帐户生成新的SSH密钥
  • 使用aws ssm put-parameter --name build_ssh_key --type String --value "$(cat id_rsa)"将此ssh密钥存储在aws参数存储中理想情况下使用SecureString而不是String但是我之后使用的指南只是使用字符串所以我不确定命令行是否需要任何额外的参数
  • 进入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."[email protected]:".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:
    - '**/*'

6
投票

我自己遇到了这个问题,由于@ matt-bucci的精彩建议,我能够提出一个看似强大的解决方案。

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

  1. 我创建了一个新的SSH密钥,供these instructions之后的“机器用户”使用。我在这种情况下使用机器用户,因此不需要为每个项目生成新的ssh密钥,也不需要为多个私有子模块的潜在支持生成新的ssh密钥
  2. 我将私钥存储在AWS参数存储中作为SecureString。这实际上并没有改变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: 
# https://stackoverflow.com/questions/42712542/how-to-auto-deploying-git-repositories-with-submodules-on-aws
version: 0.2  # Always use version 2
env:
  variables:
    # The remote origin that will be used if building through CodePipeline
    remote_origin: "[email protected]: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...

此安装脚本执行三个不连续的步骤

  1. 它安装并启用用于访问私有存储库的ssh私钥
  2. 它确定是否存在.git文件夹 - 如果没有,则脚本将初始化git并检出正在构建的确切提交。注意:根据AWS文档,不保证$CODEBUILD_RESOLVED_SOURCE_VERSION envar存在于CodePipeline版本中。但是,我没有看到这种失败
  3. 最后,它实际上得到了子模块

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

现在已经要求更好的功能2年了:https://forums.aws.amazon.com/thread.jspa?threadID=248267

Edited January, 23, 2019

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

但是,使用CodePipeline时,“Source”操作将克隆存储库,检出相应的分支,然后伪造原始文件而不使用.git文件夹。这意味着我们必须初始化github存储库以访问子模块


4
投票

虽然@MattBucci的答案有效,但它有一点需要注意,你只能拉一个特定的分支,而不是子模块正在使用的特定提交。

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

1)使用以下内容创建一个git pre-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

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

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

#!/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

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

3)转到AWS Code构建项目

Developer Tools > CodeBuild > Build projects > YOUR_PROJECT > Edit Environment

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

您可以将其转换为online,或使用任何工具或编程语言。

enter image description here

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

version: 0.2

phases:
  pre_build:
    commands:
      - bash build/aws-pre-build.sh
...

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

#!/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


附加功能

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

如果它不匹配,则表示谁曾推,没有git钩子。

#!/bin/bash

$MODULE_DIR=module

echo "- Checking submodules integrity"

SUBMODULE_TRACKING_FILE=.submodule-hash


#   Check 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 submodule actual hash
SUBMODULE_HASH=$(git ls-tree $(git symbolic-ref --short HEAD) $MODULE_DIR/ | awk '{ print $3 }')

if [[ ! -e $SUBMODULE_TRACKING_FILE ]]; then

    echo "ERROR: $SUBMODULE_TRACKING_FILE file not found."
    submoduleError

    exit 1
fi

#   Custom submodule hash - The is used by AWS Code Build
SUBMODULE_TRACKING_FILE_HASH=$(cat $SUBMODULE_TRACKING_FILE)

if [[ "$SUBMODULE_TRACKING_FILE_HASH" != "$SUBMODULE_HASH"  ]]; then

    echo "ERROR: $SUBMODULE_TRACKING_FILE file content does not match submodule hash: $SUBMODULE_HASH"

    echo -e "\tYou should have pre-commit && post-commit hook enabled or update $SUBMODULE_TRACKING_FILE manually:"
    echo -e "\tcmd: git ls-tree $(git symbolic-ref --short HEAD) $MODULE_DIR/ | awk '{ print \$3 }' > $SUBMODULE_TRACKING_FILE"

    exit 1
fi

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

git ls-tree $(git symbolic-ref --short HEAD) module/ | awk '{ print \$3 }' > .submodule-hash

1
投票

如果您使用CodeCommit作为存储库,则不需要SSH。使用AWS CLI Credential Helper并克隆https。

git config --global credential.helper '!aws codecommit credential-helper $@'
git config --global credential.UseHttpPath true
git clone https://git-codecommit.[region].amazonaws.com/v1/repos/[repo]
© www.soinside.com 2019 - 2024. All rights reserved.