我的git存储库中有一个子模块,我的目录结构就像,
app
-- folder1
-- folder2
-- submodule @5855
我已使用autodeploy服务在AWS上部署了我的代码。 现在,在服务器上,我在父目录中有代码,但子模块目录是空的。
Q1)如何在子模块中获取数据。我在服务器上的存储库不是git存储库。我是否需要先将其转换为git repo,然后运行submodule
命令才能获得它?
Q2)我如何自动化子模块部署?
由于
答案 0 :(得分:8)
这是对我有用的
我们将重新初始化git存储库,然后在部署的构建阶段触发子模块克隆,从本质上打补丁以支持codepipeline / codebuild中的子模块
aws ssm put-parameter --name build_ssh_key --type String --value "$(cat id_rsa)"
将此ssh密钥存储在aws参数存储区中,最好使用SecureString而不是String,但是我遵循的指南只是使用了string,所以我不确定命令行是否需要任何额外的参数然后使您的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:
- '**/*'
答案 1 :(得分:6)
我自己遇到了这个问题,由于@ matt-bucci提出了很棒的建议,我得以提出一个健壮的解决方案。
我的特定用例略有不同-我正在使用Lambda层来减少lambda冗余,但仍需要将这些层作为子模块包含在Lambda函数存储库中,以便CodeBuild可以构建和测试PR。我也使用CodePipeline来协助持续交付-所以我需要一个可以同时与CodePipeline和CodeBuild一起使用的系统
我创建了一个新的SSH密钥,供these instructions之后的“机器用户”使用。在这种情况下,我使用的是计算机用户,因此不需要为每个项目以及潜在的多个私有子模块支持生成新的ssh密钥
我将私钥作为SecureString存储在AWS Parameter Store中。这实际上并没有改变CodeBuild中的任何内容,因为它足够聪明,只知道如何解密密钥
我为AWS托管属性赋予了“ codebuild”角色:AmazonSSMReadOnlyAccess-允许CodeBuild访问私钥
我使用@ 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: "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文档,不能{em>保证出现在$CODEBUILD_RESOLVED_SOURCE_VERSION
envar中,而不能在CodePipeline构建中出现。但是,我没有看到失败
最后,它实际上获得了子模块
显然,这不是解决此问题的好方法。但是,鉴于CodePipeline的(不必要)限制,这是我能想到的最好的方法。此过程的副作用是“源” CodePipeline阶段完全没有用,因为我们只是覆盖已存档的源文件-它仅用于侦听对存储库的更改
人们要求更好的功能已有2年以上: https://forums.aws.amazon.com/thread.jspa?threadID=248267
我(以艰难的方式)意识到我以前的回答不支持CodePipeline构建,仅直接通过CodeBuild运行。当CodeBuild响应GitHub Webhook时,它将克隆整个GitHub存储库,包括.git文件夹
但是,当使用CodePipeline时,“源”操作将克隆存储库,签出适当的分支,然后在没有.git文件夹的情况下原始文件 。这意味着我们必须初始化github存储库才能访问子模块
答案 2 :(得分:4)
整天紧张了一下之后,我发现了一个简单的解决方案(用于代码管道),不需要在buildspec中使用任何SSH密钥。我正在使用Bitbucket,但我认为这将对其他提供商有用。我还通过https克隆了我的子模块,我不确定这是否是必需条件。
配置您的构建角色以添加客户管理的UseConnection权限,以使您的构建操作可以访问为源配置的凭据。来自AWS的文档在这里: https://docs.aws.amazon.com/codepipeline/latest/userguide/troubleshooting.html#codebuild-role-connections
设置环境以包括 git-credential-helper:是,然后在buildspec.yml中克隆子模块:
就是这样!可以使用子模块进行构建,而不必为要使用的每个子模块进行一堆关键配置。
如果最终对人们有用的话,也许是对文档的很好补充。
答案 3 :(得分:3)
@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对其进行转换,也可以使用任何工具或编程语言。
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之前还有其他步骤(例如,位桶管道或类似工具),则可以检查实际的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
答案 4 :(得分:2)
我在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线程。他们已经提到,
子模块必须配置为https而不是ssh。
我认为这没有用,将submodule
设置为ssh
的人会发生什么。我也做了同样的事情,这是我的.gitmodules
文件。
[submodule "common"]
path = common
url = git@bitbucket.org:organization_id/common.git
真的,我不想将其更改为https
。然后,我从中发现了这篇Working with Git Submodules in CodePipeline文章。我想想像一下我为解决此问题所做的工作,并且在该article中没有提到一个错误。让我们以更安全的方式进行操作。
首先转到AWS Key Management Service (KMS)并转到Customer managed keys
部分,然后单击Create key
创建密钥。
Symmetric
,然后单击Next
。bitbucket-credentials
)创建Alias
,然后单击Next
。AWS Role
来配置Developer Tools on AWS中的任何一个,因此在我的情况下,我为AWS CodeBuild创建了一个AWS Role
调用ecsCodeBuildRole
并给出Define key administrative permissions
,然后点击Next
。Define key usage permissions
输入AWS Role
,然后单击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
,解决这个问题。
答案 5 :(得分:0)
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]
答案 6 :(得分:0)
从发现子模块问题到现在已经很久了。但是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。
答案 7 :(得分:0)
借用@MattBucci和@JoshuaEvans的概念。这就是我们所做的。由于ssh的严格访问/安全问题,我们无法在管道中安装git。因此,我们最终通过HTTP进行了此操作。
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
希望这会有所帮助!