我的git存储库中有一个子模块,我的目录结构是这样的,
app
-- folder1
-- folder2
-- submodule @5855
我已使用autodeploy服务在AWS上部署了我的代码。现在,在服务器上,我在父目录中有代码,但子模块目录是空的。
Q1)如何在子模块中获取数据。我在服务器上的存储库不是git存储库。我是否需要先将其转换为git repo,然后运行submodule
命令才能获得它?
Q2)如何自动化子模块部署?
谢谢
这对我有用
我们将重新初始化git存储库,然后在部署的构建阶段触发子模块克隆,基本上修补了对codepipeline / codebuild中的子模块的支持
aws ssm put-parameter --name build_ssh_key --type String --value "$(cat id_rsa)"
将此ssh密钥存储在aws参数存储中理想情况下使用SecureString而不是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."[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:
- '**/*'
我自己遇到了这个问题,由于@ matt-bucci的精彩建议,我能够提出一个看似强大的解决方案。
我的具体用例略有不同 - 我使用Lambda Layers来减少lambda冗余,但仍需要将这些层作为子模块包含在Lambda函数存储库中,以便CodeBuild可以构建和测试PR。我也在使用CodePipeline来协助持续交付 - 所以我需要一个可以同时使用CodePipeline和CodeBuild的系统
# 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...
此安装脚本执行三个不连续的步骤
$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时,“Source”操作将克隆存储库,检出相应的分支,然后伪造原始文件而不使用.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 $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之前有一个额外的步骤,比如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
如果您使用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]