如何在 AWS 上自动部署带有子模块的 git 个存储库?
How to auto deploying git repositories with submodules on AWS?
我的 git 存储库中有一个子模块,我的目录结构如下,
app
-- folder1
-- folder2
-- submodule @5855
我已经使用自动部署服务在 AWS 上部署了我的代码。
现在,在服务器上,我在父目录中有代码,但子模块目录是空的。
Q1) 如何获取子模块中的数据。我在服务器上的存储库不是 git 存储库。我是否需要先将其转换为 git 存储库,然后再将其转换为 运行 submodule
命令才能获取它?
Q2) 我怎样才能自动部署子模块?
谢谢
编辑:Codebuild 现在有一个“子模块”标志 https://docs.aws.amazon.com/codebuild/latest/APIReference/API_GitSubmodulesConfig.html
这是对我有用的方法
我们将重新初始化 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 用户对您的参数库的读取权限,我刚刚授予对 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:
- '**/*'
我自己 运行 解决了这个问题,多亏了 @matt-bucci 的精彩建议,我才能够想出一个看似可靠的解决方案。
我的具体用例略有不同 - 我正在使用 Lambda 层来减少 lambda 冗余,但仍需要将这些层作为子模块包含在 Lambda 函数存储库中,以便 CodeBuild 可以构建和测试 PR。我也在使用 CodePipeline 来协助持续交付 - 所以我需要一个可以单独使用 CodePipeline 和 CodeBuild 的系统
我创建了一个新的 SSH 密钥供 these instructions 之后的 "machine user" 使用。在这种情况下,我使用的是机器用户,因此不需要为 每个 项目生成新的 ssh 密钥,也不需要为多个私有子模块提供潜在支持
我将私钥作为 SecureString 存储在 AWS Parameter Store 中。这实际上并没有改变 CodeBuild 中的任何内容,因为它足够聪明,只知道如何解密密钥
我给了 "codebuild" 角色 AWS 托管 属性:AmazonSSMReadOnlyAccess - 允许 CodeBuild 访问私钥
我制作了我的 buildspec.yml 文件,使用了@matt-bucci 建议的一堆命令,以及一些新命令
# 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:
#
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...
此安装脚本执行三个独立的步骤
它安装并启用用于访问私有存储库的 ssh 私钥
它确定是否有 .git 文件夹 - 如果没有,则脚本将初始化 git 并检查 exact 正在构建的提交。 注意: 根据 AWS 文档,$CODEBUILD_RESOLVED_SOURCE_VERSION
envar 不会 gu运行teed 出现在 CodePipeline 构建中.但是,我没有看到这个失败
终于真正拿到子模块了
显然,这不是解决此问题的好方法。但是,考虑到 CodePipeline 的(不必要的)限制,这是我能想到的最好的方法。这个过程的一个副作用是 "Source" CodePipeline 阶段完全没有价值,因为我们只是覆盖了存档的源文件——它只用于监听对存储库的更改
两年多来一直要求更好的功能:
https://forums.aws.amazon.com/thread.jspa?threadID=248267
2019 年 1 月 23 日编辑
我意识到(艰难地)我之前的回复不支持 CodePipeline 构建,只能直接通过 CodeBuild 构建 运行。当 CodeBuild 响应 GitHub Webhook 时,它将克隆整个 GitHub 存储库,包括 .git 文件夹
但是,当使用 CodePipeline 时,"Source" 操作将克隆存储库,检查适当的 b运行ch,然后生成原始文件 而没有 .git 文件夹。这意味着我们必须初始化 github 存储库才能访问子模块
虽然@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 }' > $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
的环境变量,其值将是 ssh 密钥 base 64 编码。 (不能换行,否则不行)
您可以转换它 online,或者使用任何工具或编程语言。
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 }')
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
如果您使用 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]
很久没发现子模块的问题了。但是 aws 无法修复它。因此 codepipeline 无法将 .git 目录发送到 codebuild。所以我们必须发明新的双臂,我的解决方法是 buildspec.yml 预构建命令
rm -rf $PWD/*
git clone --depth 1 https://<REPO NAME> -b develop .
git submodule update --init --recursive
AWS 快点,因为我们的团队正在考虑搬回 github。
借鉴@MattBucci 和@JoshuaEvans 的概念。这是我们所做的。我们无法在管道中安装 git,因为 ssh 存在严格的 access/security 问题。所以我们最终改为通过 HTTP 执行此操作。
- 我创建了一个新的 Github 个人访问令牌
- 我将 PAT 作为
安全字符串。这实际上并没有改变任何东西
CodeBuild,因为它足够聪明,只知道如何解密
键
- 我给了 "codebuild" 角色来读取 Secrets manager
- 我使用一堆命令创建了我的 buildspec.yml 文件
@matt-bucci 和@JoshuaEvans 以及一些新建议
version: 0.2
env:
variables:
token: " token "
secrets-manager:
personalAccessToken: $personalAccessTokenPath
phases:
install:
runtime-versions:
nodejs: 12
commands:
- cd <to the folder where you want the submodules>
- wget --header="Authorization:$token$personalAccessToken" --content-disposition https://github.com/uri/zipball/$branch/
- unzip project*.zip -d project-folder
- rm -rf project*.zip
- cd project-folder
- mv project*/* .
- rm -rf project*
- cd <back to your base folder where the buildspec is>
pre_build:
commands:
- xxx
build:
commands:
- xxx
post_build:
commands:
- xxx
artifacts:
files:
- '**/*'
base-directory: dist
希望对您有所帮助!
我在 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
所以我用谷歌搜索了上面的错误,并从 AWS 论坛得到了这个 DOWNLOAD_SOURCE Fails with Git submodules 帖子。他们提到,
The submodules must be configured as https and not ssh.
我认为这没有用,有人将 submodule
设置为 ssh
会发生什么。我也做了同样的事情,这是我的 .gitmodules
文件。
[submodule "common"]
path = common
url = git@bitbucket.org:organization_id/common.git
真的不想改成https
。然后我发现了这个Working with Git Submodules in CodePipeline article from medium. I would like to visualize what I did to solve this issue and there was an error that didn't mention in that article。让我们以更安全的方式来做到这一点。
首先转到 AWS Key Management Service (KMS) 并转到 Customer managed keys
部分并单击 Create key
创建密钥。
- 单击
Symmetric
并单击 Next
。
- 输入任何名称(例如:-
bitbucket-credentials
)以创建 Alias
并单击 Next
。
- 很可能您已经有一个
AWS Role
来配置任何 AWS 上的开发人员工具,所以在我的例子中,我创建了一个 AWS Role
调用 ecsCodeBuildRole
for AWS CodeBuild 并为其输入 Define key administrative permissions
然后单击 Next
。
- 接下来为您的
AWS Role
输入 Define key usage permissions
然后点击 Next
。
- 最后回顾一下您到目前为止所做的,然后单击
Finish
创建 CMK。
- 您可以像下面这样查看。
所以 AWS Key Management Service (KMS) 部分已完成,现在转到 AWS Systems Manager 并找到 Parameter Store
部分。单击 Create parameter
。
- 只要将它命名为
id_rsa
并像下面一样放置相同的东西。
- 对于
value
部分,只需在您的终端中使用 运行 cat ~/.ssh/id_rsa
命令,您将获得如下输出。将其添加到 value
部分。
-----BEGIN RSA PRIVATE KEY-----
qdjbXp+42VTnccC7pxOZcofomfwGXPWuqcv99sQEPtToODvGIxWoooJUpb6qMIWY
1zccEuwAhmqcPvpsJyWhcctZB/wWglNvViZcOYjrQ8HBUBKJT8pF
-----END RSA PRIVATE KEY-----
创建另一个参数并将其命名为id_rsa.pub
。按照与上述相同的步骤进行操作。
对于 value
部分,只需在您的终端中使用 运行 cat ~/.ssh/id_rsa.pub
命令,您将获得如下输出。将其添加到 value
部分。
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGtf8jjkogWxRGNGjJlOZ1G+pWExgDOdA5wVML6TMTT2YtvhPJD60nPx5TfA8zRzGWubwrPp40SPAhSs5wiAAg38HlS4pz9X wasdkiller@wasdkiller
作为我的研究(也许我错了,请纠正我)我没有任何其他方法可以将 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
当您继续时,您肯定会遇到以下错误,
Decrypted Variables Error: AccessDeniedException: User: arn:aws:sts::organization_id:assumed-role/ecsCodeBuildRole/AWSCodeBuild-12896abb-bdcf-4cfc-a12b-bcf30d6e96ab is not authorized to perform: ssm:GetParameters on resource: arn:aws:ssm:ap-southeast-2:organization_id:parameter/wasd status code: 400, request id: 23b94bc2-961e-4d86-9b73-d16e3bda357c
它会要求您提供 ssm:GetParameters
权限,只需附加 AmazonSSMReadOnlyAccess
策略或使用 ssm:GetParameters
权限手动创建策略并将其附加到您的 AWS Role
,它会解决这个问题。
一整天都在苦思冥想之后,我找到了一个简单的解决方案(用于代码管道),不需要在构建规范 中处理任何 SSH 密钥。我正在使用 Bitbucket,但我认为这适用于其他提供商。我也在通过 https 克隆我的子模块,我不确定这是否是必需的。
配置您的源以对存储库进行完整克隆。这将传递您需要的 git 元数据。
配置您的构建角色以添加 customer-managed UseConnection 权限,使您的构建操作能够访问您为源配置的凭据。此处来自 AWS 的文档:
https://docs.aws.amazon.com/codepipeline/latest/userguide/troubleshooting.html#codebuild-role-connections
设置您的环境以包含 git-credential-helper: yes 并克隆 buildspec.yml:
中的子模块
就是这样!子模块将可用于构建,而无需为您要使用的每个子模块做一堆关键配置。
如果最终对人们有用,这可能是对文档的一个很好的补充。
我的 git 存储库中有一个子模块,我的目录结构如下,
app
-- folder1
-- folder2
-- submodule @5855
我已经使用自动部署服务在 AWS 上部署了我的代码。 现在,在服务器上,我在父目录中有代码,但子模块目录是空的。
Q1) 如何获取子模块中的数据。我在服务器上的存储库不是 git 存储库。我是否需要先将其转换为 git 存储库,然后再将其转换为 运行 submodule
命令才能获取它?
Q2) 我怎样才能自动部署子模块?
谢谢
编辑:Codebuild 现在有一个“子模块”标志 https://docs.aws.amazon.com/codebuild/latest/APIReference/API_GitSubmodulesConfig.html
这是对我有用的方法
我们将重新初始化 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 用户对您的参数库的读取权限,我刚刚授予对 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:
- '**/*'
我自己 运行 解决了这个问题,多亏了 @matt-bucci 的精彩建议,我才能够想出一个看似可靠的解决方案。
我的具体用例略有不同 - 我正在使用 Lambda 层来减少 lambda 冗余,但仍需要将这些层作为子模块包含在 Lambda 函数存储库中,以便 CodeBuild 可以构建和测试 PR。我也在使用 CodePipeline 来协助持续交付 - 所以我需要一个可以单独使用 CodePipeline 和 CodeBuild 的系统
我创建了一个新的 SSH 密钥供 these instructions 之后的 "machine user" 使用。在这种情况下,我使用的是机器用户,因此不需要为 每个 项目生成新的 ssh 密钥,也不需要为多个私有子模块提供潜在支持
我将私钥作为 SecureString 存储在 AWS Parameter Store 中。这实际上并没有改变 CodeBuild 中的任何内容,因为它足够聪明,只知道如何解密密钥
我给了 "codebuild" 角色 AWS 托管 属性:AmazonSSMReadOnlyAccess - 允许 CodeBuild 访问私钥
我制作了我的 buildspec.yml 文件,使用了@matt-bucci 建议的一堆命令,以及一些新命令
# 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:
#
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...
此安装脚本执行三个独立的步骤
它安装并启用用于访问私有存储库的 ssh 私钥
它确定是否有 .git 文件夹 - 如果没有,则脚本将初始化 git 并检查 exact 正在构建的提交。 注意: 根据 AWS 文档,
$CODEBUILD_RESOLVED_SOURCE_VERSION
envar 不会 gu运行teed 出现在 CodePipeline 构建中.但是,我没有看到这个失败终于真正拿到子模块了
显然,这不是解决此问题的好方法。但是,考虑到 CodePipeline 的(不必要的)限制,这是我能想到的最好的方法。这个过程的一个副作用是 "Source" CodePipeline 阶段完全没有价值,因为我们只是覆盖了存档的源文件——它只用于监听对存储库的更改
两年多来一直要求更好的功能: https://forums.aws.amazon.com/thread.jspa?threadID=248267
2019 年 1 月 23 日编辑
我意识到(艰难地)我之前的回复不支持 CodePipeline 构建,只能直接通过 CodeBuild 构建 运行。当 CodeBuild 响应 GitHub Webhook 时,它将克隆整个 GitHub 存储库,包括 .git 文件夹
但是,当使用 CodePipeline 时,"Source" 操作将克隆存储库,检查适当的 b运行ch,然后生成原始文件 而没有 .git 文件夹。这意味着我们必须初始化 github 存储库才能访问子模块
虽然@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 }' > $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
的环境变量,其值将是 ssh 密钥 base 64 编码。 (不能换行,否则不行)
您可以转换它 online,或者使用任何工具或编程语言。
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 }')
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
如果您使用 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]
很久没发现子模块的问题了。但是 aws 无法修复它。因此 codepipeline 无法将 .git 目录发送到 codebuild。所以我们必须发明新的双臂,我的解决方法是 buildspec.yml 预构建命令
rm -rf $PWD/*
git clone --depth 1 https://<REPO NAME> -b develop .
git submodule update --init --recursive
AWS 快点,因为我们的团队正在考虑搬回 github。
借鉴@MattBucci 和@JoshuaEvans 的概念。这是我们所做的。我们无法在管道中安装 git,因为 ssh 存在严格的 access/security 问题。所以我们最终改为通过 HTTP 执行此操作。
- 我创建了一个新的 Github 个人访问令牌
- 我将 PAT 作为 安全字符串。这实际上并没有改变任何东西 CodeBuild,因为它足够聪明,只知道如何解密 键
- 我给了 "codebuild" 角色来读取 Secrets manager
- 我使用一堆命令创建了我的 buildspec.yml 文件 @matt-bucci 和@JoshuaEvans 以及一些新建议
version: 0.2
env:
variables:
token: " token "
secrets-manager:
personalAccessToken: $personalAccessTokenPath
phases:
install:
runtime-versions:
nodejs: 12
commands:
- cd <to the folder where you want the submodules>
- wget --header="Authorization:$token$personalAccessToken" --content-disposition https://github.com/uri/zipball/$branch/
- unzip project*.zip -d project-folder
- rm -rf project*.zip
- cd project-folder
- mv project*/* .
- rm -rf project*
- cd <back to your base folder where the buildspec is>
pre_build:
commands:
- xxx
build:
commands:
- xxx
post_build:
commands:
- xxx
artifacts:
files:
- '**/*'
base-directory: dist
希望对您有所帮助!
我在 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
所以我用谷歌搜索了上面的错误,并从 AWS 论坛得到了这个 DOWNLOAD_SOURCE Fails with Git submodules 帖子。他们提到,
The submodules must be configured as https and not ssh.
我认为这没有用,有人将 submodule
设置为 ssh
会发生什么。我也做了同样的事情,这是我的 .gitmodules
文件。
[submodule "common"]
path = common
url = git@bitbucket.org:organization_id/common.git
真的不想改成https
。然后我发现了这个Working with Git Submodules in CodePipeline article from medium. I would like to visualize what I did to solve this issue and there was an error that didn't mention in that article。让我们以更安全的方式来做到这一点。
首先转到 AWS Key Management Service (KMS) 并转到 Customer managed keys
部分并单击 Create key
创建密钥。
- 单击
Symmetric
并单击Next
。
- 输入任何名称(例如:-
bitbucket-credentials
)以创建Alias
并单击Next
。
- 很可能您已经有一个
AWS Role
来配置任何 AWS 上的开发人员工具,所以在我的例子中,我创建了一个AWS Role
调用ecsCodeBuildRole
for AWS CodeBuild 并为其输入Define key administrative permissions
然后单击Next
。
- 接下来为您的
AWS Role
输入Define key usage permissions
然后点击Next
。
- 最后回顾一下您到目前为止所做的,然后单击
Finish
创建 CMK。
- 您可以像下面这样查看。
所以 AWS Key Management Service (KMS) 部分已完成,现在转到 AWS Systems Manager 并找到 Parameter Store
部分。单击 Create parameter
。
- 只要将它命名为
id_rsa
并像下面一样放置相同的东西。
- 对于
value
部分,只需在您的终端中使用 运行cat ~/.ssh/id_rsa
命令,您将获得如下输出。将其添加到value
部分。
-----BEGIN RSA PRIVATE KEY-----
qdjbXp+42VTnccC7pxOZcofomfwGXPWuqcv99sQEPtToODvGIxWoooJUpb6qMIWY
1zccEuwAhmqcPvpsJyWhcctZB/wWglNvViZcOYjrQ8HBUBKJT8pF
-----END RSA PRIVATE KEY-----
创建另一个参数并将其命名为
id_rsa.pub
。按照与上述相同的步骤进行操作。对于
value
部分,只需在您的终端中使用 运行cat ~/.ssh/id_rsa.pub
命令,您将获得如下输出。将其添加到value
部分。
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGtf8jjkogWxRGNGjJlOZ1G+pWExgDOdA5wVML6TMTT2YtvhPJD60nPx5TfA8zRzGWubwrPp40SPAhSs5wiAAg38HlS4pz9X wasdkiller@wasdkiller
作为我的研究(也许我错了,请纠正我)我没有任何其他方法可以将 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
当您继续时,您肯定会遇到以下错误,
Decrypted Variables Error: AccessDeniedException: User: arn:aws:sts::organization_id:assumed-role/ecsCodeBuildRole/AWSCodeBuild-12896abb-bdcf-4cfc-a12b-bcf30d6e96ab is not authorized to perform: ssm:GetParameters on resource: arn:aws:ssm:ap-southeast-2:organization_id:parameter/wasd status code: 400, request id: 23b94bc2-961e-4d86-9b73-d16e3bda357c
它会要求您提供 ssm:GetParameters
权限,只需附加 AmazonSSMReadOnlyAccess
策略或使用 ssm:GetParameters
权限手动创建策略并将其附加到您的 AWS Role
,它会解决这个问题。
一整天都在苦思冥想之后,我找到了一个简单的解决方案(用于代码管道),不需要在构建规范 中处理任何 SSH 密钥。我正在使用 Bitbucket,但我认为这适用于其他提供商。我也在通过 https 克隆我的子模块,我不确定这是否是必需的。
配置您的源以对存储库进行完整克隆。这将传递您需要的 git 元数据。
配置您的构建角色以添加 customer-managed UseConnection 权限,使您的构建操作能够访问您为源配置的凭据。此处来自 AWS 的文档: https://docs.aws.amazon.com/codepipeline/latest/userguide/troubleshooting.html#codebuild-role-connections
设置您的环境以包含 git-credential-helper: yes 并克隆 buildspec.yml:
中的子模块
就是这样!子模块将可用于构建,而无需为您要使用的每个子模块做一堆关键配置。
如果最终对人们有用,这可能是对文档的一个很好的补充。