Skip to content

Commit 939c2e0

Browse files
authored
Add instructions for executing the AWS CodeBuild workflows locally (#160)
1 parent 9b8daab commit 939c2e0

File tree

2 files changed

+223
-0
lines changed

2 files changed

+223
-0
lines changed

CONTRIBUTING.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,24 @@ GitHub provides additional document on [forking a repository](https://help.githu
4343
## Finding contributions to work on
4444
Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/awslabs/aws-lambda-cpp-runtime/labels/help%20wanted) issues is a great place to start.
4545

46+
## Running the Integration Tests Locally
47+
48+
The integration testing for the project creates, invokes, and deletes, Lambda functions.
49+
These tests typically run AWS CodeBuild, but may also be executed locally
50+
51+
Prerequisites:
52+
* install Docker
53+
* configure AWS credentials, need at least permissions to Create, Delete, and Invoke Lambda functions
54+
* an IAM role, named exactly `integration-tests`, must exist in the account.
55+
* The role must also be assumable by Lambda.
56+
* (optional) attach AWSLambdaBasicExecutionRole managed policy to the role, so that the test function logs are saved to CloudWatch
57+
58+
Then, to iterate on a single workflow:
59+
```
60+
docker build -t lambda-cpp-amazon-linux-2 -f ./ci/docker/amazon-linux-2 .
61+
./ci/codebuild_build.sh -c -a /tmp -i lambda-cpp-amazon-linux-2 -b ./ci/codebuild/amazon-linux-2.yml
62+
```
63+
4664

4765
## Code of Conduct
4866
This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).

ci/codebuild_build.sh

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
#!/bin/bash
2+
3+
function allOSRealPath() {
4+
if isOSWindows
5+
then
6+
path=""
7+
case $1 in
8+
.* ) path="$PWD/${1#./}" ;;
9+
/* ) path="$1" ;;
10+
* ) path="/$1" ;;
11+
esac
12+
13+
echo "/$path" | sed -e 's/\\/\//g' -e 's/://' -e 's/./\U&/3'
14+
else
15+
case $1 in
16+
/* ) echo "$1"; exit;;
17+
* ) echo "$PWD/${1#./}"; exit;;
18+
esac
19+
fi
20+
}
21+
22+
function isOSWindows() {
23+
if [ $OSTYPE == "msys" ]
24+
then
25+
return 0
26+
else
27+
return 1
28+
fi
29+
}
30+
31+
function usage {
32+
echo "usage: codebuild_build.sh [-i image_name] [-a artifact_output_directory] [options]"
33+
echo "Required:"
34+
echo " -i Used to specify the customer build container image."
35+
echo " -a Used to specify an artifact output directory."
36+
echo "Options:"
37+
echo " -l IMAGE Used to override the default local agent image."
38+
echo " -r Used to specify a report output directory."
39+
echo " -s Used to specify source information. Defaults to the current working directory for primary source."
40+
echo " * First (-s) is for primary source"
41+
echo " * Use additional (-s) in <sourceIdentifier>:<sourceLocation> format for secondary source"
42+
echo " * For sourceIdentifier, use a value that is fewer than 128 characters and contains only alphanumeric characters and underscores"
43+
echo " -c Use the AWS configuration and credentials from your local host. This includes ~/.aws and any AWS_* environment variables."
44+
echo " -p Used to specify the AWS CLI Profile."
45+
echo " -b FILE Used to specify a buildspec override file. Defaults to buildspec.yml in the source directory."
46+
echo " -m Used to mount the source directory to the customer build container directly."
47+
echo " -d Used to run the build container in docker privileged mode."
48+
echo " -e FILE Used to specify a file containing environment variables."
49+
echo " (-e) File format expectations:"
50+
echo " * Each line is in VAR=VAL format"
51+
echo " * Lines beginning with # are processed as comments and ignored"
52+
echo " * Blank lines are ignored"
53+
echo " * File can be of type .env or .txt"
54+
echo " * There is no special handling of quotation marks, meaning they will be part of the VAL"
55+
exit 1
56+
}
57+
58+
image_flag=false
59+
artifact_flag=false
60+
awsconfig_flag=false
61+
mount_src_dir_flag=false
62+
docker_privileged_mode_flag=false
63+
64+
while getopts "cmdi:a:r:s:b:e:l:p:h" opt; do
65+
case $opt in
66+
i ) image_flag=true; image_name=$OPTARG;;
67+
a ) artifact_flag=true; artifact_dir=$OPTARG;;
68+
r ) report_dir=$OPTARG;;
69+
b ) buildspec=$OPTARG;;
70+
c ) awsconfig_flag=true;;
71+
m ) mount_src_dir_flag=true;;
72+
d ) docker_privileged_mode_flag=true;;
73+
s ) source_dirs+=("$OPTARG");;
74+
e ) environment_variable_file=$OPTARG;;
75+
l ) local_agent_image=$OPTARG;;
76+
p ) aws_profile=$OPTARG;;
77+
h ) usage; exit;;
78+
\? ) echo "Unknown option: -$OPTARG" >&2; exit 1;;
79+
: ) echo "Missing option argument for -$OPTARG" >&2; exit 1;;
80+
* ) echo "Invalid option: -$OPTARG" >&2; exit 1;;
81+
esac
82+
done
83+
84+
if ! $image_flag
85+
then
86+
echo "The image name flag (-i) must be included for a build to run" >&2
87+
fi
88+
89+
if ! $artifact_flag
90+
then
91+
echo "The artifact directory (-a) must be included for a build to run" >&2
92+
fi
93+
94+
if ! $image_flag || ! $artifact_flag
95+
then
96+
exit 1
97+
fi
98+
99+
docker_command="docker run -it "
100+
if isOSWindows
101+
then
102+
docker_command+="-v //var/run/docker.sock:/var/run/docker.sock -e "
103+
else
104+
docker_command+="-v /var/run/docker.sock:/var/run/docker.sock -e "
105+
fi
106+
107+
docker_command+="\"IMAGE_NAME=$image_name\" -e \
108+
\"ARTIFACTS=$(allOSRealPath "$artifact_dir")\""
109+
110+
if [ -n "$report_dir" ]
111+
then
112+
docker_command+=" -e \"REPORTS=$(allOSRealPath "$report_dir")\""
113+
fi
114+
115+
if [ -z "$source_dirs" ]
116+
then
117+
docker_command+=" -e \"SOURCE=$(allOSRealPath "$PWD")\""
118+
else
119+
for index in "${!source_dirs[@]}"; do
120+
if [ $index -eq 0 ]
121+
then
122+
docker_command+=" -e \"SOURCE=$(allOSRealPath "${source_dirs[$index]}")\""
123+
else
124+
identifier=${source_dirs[$index]%%:*}
125+
src_dir=$(allOSRealPath "${source_dirs[$index]#*:}")
126+
127+
docker_command+=" -e \"SECONDARY_SOURCE_$index=$identifier:$src_dir\""
128+
fi
129+
done
130+
fi
131+
132+
if [ -n "$buildspec" ]
133+
then
134+
docker_command+=" -e \"BUILDSPEC=$(allOSRealPath "$buildspec")\""
135+
fi
136+
137+
if [ -n "$environment_variable_file" ]
138+
then
139+
environment_variable_file_path=$(allOSRealPath "$environment_variable_file")
140+
environment_variable_file_dir=$(dirname "$environment_variable_file_path")
141+
environment_variable_file_basename=$(basename "$environment_variable_file")
142+
docker_command+=" -v \"$environment_variable_file_dir:/LocalBuild/envFile/\" -e \"ENV_VAR_FILE=$environment_variable_file_basename\""
143+
fi
144+
145+
if [ -n "$local_agent_image" ]
146+
then
147+
docker_command+=" -e \"LOCAL_AGENT_IMAGE_NAME=$local_agent_image\""
148+
fi
149+
150+
if $awsconfig_flag
151+
then
152+
if [ -d "$HOME/.aws" ]
153+
then
154+
configuration_file_path=$(allOSRealPath "$HOME/.aws")
155+
docker_command+=" -e \"AWS_CONFIGURATION=$configuration_file_path\""
156+
else
157+
docker_command+=" -e \"AWS_CONFIGURATION=NONE\""
158+
fi
159+
160+
if [ -n "$aws_profile" ]
161+
then
162+
docker_command+=" -e \"AWS_PROFILE=$aws_profile\""
163+
fi
164+
165+
docker_command+="$(env | grep ^AWS_ | while read -r line; do echo " -e \"$line\""; done )"
166+
fi
167+
168+
if $mount_src_dir_flag
169+
then
170+
docker_command+=" -e \"MOUNT_SOURCE_DIRECTORY=TRUE\""
171+
fi
172+
173+
if $docker_privileged_mode_flag
174+
then
175+
docker_command+=" -e \"DOCKER_PRIVILEGED_MODE=TRUE\""
176+
fi
177+
178+
if isOSWindows
179+
then
180+
docker_command+=" -e \"INITIATOR=$USERNAME\""
181+
else
182+
docker_command+=" -e \"INITIATOR=$USER\""
183+
fi
184+
185+
if [ -n "$local_agent_image" ]
186+
then
187+
docker_command+=" $local_agent_image"
188+
else
189+
docker_command+=" public.ecr.aws/codebuild/local-builds:latest"
190+
fi
191+
192+
# Note we do not expose the AWS_SECRET_ACCESS_KEY or the AWS_SESSION_TOKEN
193+
exposed_command=$docker_command
194+
secure_variables=( "AWS_SECRET_ACCESS_KEY=" "AWS_SESSION_TOKEN=")
195+
for variable in "${secure_variables[@]}"
196+
do
197+
exposed_command="$(echo $exposed_command | sed "s/\($variable\)[^ ]*/\1********\"/")"
198+
done
199+
200+
echo "Build Command:"
201+
echo ""
202+
echo $exposed_command
203+
echo ""
204+
205+
eval $docker_command

0 commit comments

Comments
 (0)