@aws/ml-container-creator 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/LICENSE-THIRD-PARTY +68620 -0
- package/NOTICE +2 -0
- package/README.md +106 -0
- package/bin/cli.js +365 -0
- package/config/defaults.json +32 -0
- package/config/presets/transformers-djl.json +26 -0
- package/config/presets/transformers-gpu.json +24 -0
- package/config/presets/transformers-lmi.json +27 -0
- package/package.json +129 -0
- package/servers/README.md +419 -0
- package/servers/base-image-picker/catalogs/model-servers.json +1191 -0
- package/servers/base-image-picker/catalogs/python-slim.json +38 -0
- package/servers/base-image-picker/catalogs/triton-backends.json +51 -0
- package/servers/base-image-picker/catalogs/triton.json +38 -0
- package/servers/base-image-picker/index.js +495 -0
- package/servers/base-image-picker/manifest.json +17 -0
- package/servers/base-image-picker/package.json +15 -0
- package/servers/hyperpod-cluster-picker/LICENSE +202 -0
- package/servers/hyperpod-cluster-picker/index.js +424 -0
- package/servers/hyperpod-cluster-picker/manifest.json +14 -0
- package/servers/hyperpod-cluster-picker/package.json +17 -0
- package/servers/instance-recommender/LICENSE +202 -0
- package/servers/instance-recommender/catalogs/instances.json +852 -0
- package/servers/instance-recommender/index.js +284 -0
- package/servers/instance-recommender/manifest.json +16 -0
- package/servers/instance-recommender/package.json +15 -0
- package/servers/lib/LICENSE +202 -0
- package/servers/lib/bedrock-client.js +160 -0
- package/servers/lib/custom-validators.js +46 -0
- package/servers/lib/dynamic-resolver.js +36 -0
- package/servers/lib/package.json +11 -0
- package/servers/lib/schemas/image-catalog.schema.json +185 -0
- package/servers/lib/schemas/instances.schema.json +124 -0
- package/servers/lib/schemas/manifest.schema.json +64 -0
- package/servers/lib/schemas/model-catalog.schema.json +91 -0
- package/servers/lib/schemas/regions.schema.json +26 -0
- package/servers/lib/schemas/triton-backends.schema.json +51 -0
- package/servers/model-picker/catalogs/jumpstart-public.json +66 -0
- package/servers/model-picker/catalogs/popular-diffusors.json +88 -0
- package/servers/model-picker/catalogs/popular-transformers.json +226 -0
- package/servers/model-picker/index.js +1693 -0
- package/servers/model-picker/manifest.json +18 -0
- package/servers/model-picker/package.json +20 -0
- package/servers/region-picker/LICENSE +202 -0
- package/servers/region-picker/catalogs/regions.json +263 -0
- package/servers/region-picker/index.js +230 -0
- package/servers/region-picker/manifest.json +16 -0
- package/servers/region-picker/package.json +15 -0
- package/src/app.js +1007 -0
- package/src/copy-tpl.js +77 -0
- package/src/lib/accelerator-validator.js +39 -0
- package/src/lib/asset-manager.js +385 -0
- package/src/lib/aws-profile-parser.js +181 -0
- package/src/lib/bootstrap-command-handler.js +1647 -0
- package/src/lib/bootstrap-config.js +238 -0
- package/src/lib/ci-register-helpers.js +124 -0
- package/src/lib/ci-report-helpers.js +158 -0
- package/src/lib/ci-stage-helpers.js +268 -0
- package/src/lib/cli-handler.js +529 -0
- package/src/lib/comment-generator.js +544 -0
- package/src/lib/community-reports-validator.js +91 -0
- package/src/lib/config-manager.js +2106 -0
- package/src/lib/configuration-exporter.js +204 -0
- package/src/lib/configuration-manager.js +695 -0
- package/src/lib/configuration-matcher.js +221 -0
- package/src/lib/cpu-validator.js +36 -0
- package/src/lib/cuda-validator.js +57 -0
- package/src/lib/deployment-config-resolver.js +103 -0
- package/src/lib/deployment-entry-schema.js +125 -0
- package/src/lib/deployment-registry.js +598 -0
- package/src/lib/docker-introspection-validator.js +51 -0
- package/src/lib/engine-prefix-resolver.js +60 -0
- package/src/lib/huggingface-client.js +172 -0
- package/src/lib/key-value-parser.js +37 -0
- package/src/lib/known-flags-validator.js +200 -0
- package/src/lib/manifest-cli.js +280 -0
- package/src/lib/mcp-client.js +303 -0
- package/src/lib/mcp-command-handler.js +532 -0
- package/src/lib/neuron-validator.js +80 -0
- package/src/lib/parameter-schema-validator.js +284 -0
- package/src/lib/prompt-runner.js +1349 -0
- package/src/lib/prompts.js +1138 -0
- package/src/lib/registry-command-handler.js +519 -0
- package/src/lib/registry-loader.js +198 -0
- package/src/lib/rocm-validator.js +80 -0
- package/src/lib/schema-validator.js +157 -0
- package/src/lib/sensitive-redactor.js +59 -0
- package/src/lib/template-engine.js +156 -0
- package/src/lib/template-manager.js +341 -0
- package/src/lib/validation-engine.js +314 -0
- package/src/prompt-adapter.js +63 -0
- package/templates/Dockerfile +300 -0
- package/templates/IAM_PERMISSIONS.md +84 -0
- package/templates/MIGRATION.md +488 -0
- package/templates/PROJECT_README.md +439 -0
- package/templates/TEMPLATE_SYSTEM.md +243 -0
- package/templates/buildspec.yml +64 -0
- package/templates/code/chat_template.jinja +1 -0
- package/templates/code/flask/gunicorn_config.py +35 -0
- package/templates/code/flask/wsgi.py +10 -0
- package/templates/code/model_handler.py +387 -0
- package/templates/code/serve +300 -0
- package/templates/code/serve.py +175 -0
- package/templates/code/serving.properties +105 -0
- package/templates/code/start_server.py +39 -0
- package/templates/code/start_server.sh +39 -0
- package/templates/diffusors/Dockerfile +72 -0
- package/templates/diffusors/patch_image_api.py +35 -0
- package/templates/diffusors/serve +115 -0
- package/templates/diffusors/start_server.sh +114 -0
- package/templates/do/.gitkeep +1 -0
- package/templates/do/README.md +541 -0
- package/templates/do/build +83 -0
- package/templates/do/ci +681 -0
- package/templates/do/clean +811 -0
- package/templates/do/config +260 -0
- package/templates/do/deploy +1560 -0
- package/templates/do/export +306 -0
- package/templates/do/logs +319 -0
- package/templates/do/manifest +12 -0
- package/templates/do/push +119 -0
- package/templates/do/register +580 -0
- package/templates/do/run +113 -0
- package/templates/do/submit +417 -0
- package/templates/do/test +1147 -0
- package/templates/hyperpod/configmap.yaml +24 -0
- package/templates/hyperpod/deployment.yaml +71 -0
- package/templates/hyperpod/pvc.yaml +42 -0
- package/templates/hyperpod/service.yaml +17 -0
- package/templates/nginx-diffusors.conf +74 -0
- package/templates/nginx-predictors.conf +47 -0
- package/templates/nginx-tensorrt.conf +74 -0
- package/templates/requirements.txt +61 -0
- package/templates/sample_model/test_inference.py +123 -0
- package/templates/sample_model/train_abalone.py +252 -0
- package/templates/test/test_endpoint.sh +79 -0
- package/templates/test/test_local_image.sh +80 -0
- package/templates/test/test_model_handler.py +180 -0
- package/templates/triton/Dockerfile +128 -0
- package/templates/triton/config.pbtxt +163 -0
- package/templates/triton/model.py +130 -0
- package/templates/triton/requirements.txt +11 -0
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
set -u
|
|
7
|
+
set -o pipefail
|
|
8
|
+
|
|
9
|
+
# Source configuration
|
|
10
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
|
+
source "${SCRIPT_DIR}/config"
|
|
12
|
+
|
|
13
|
+
echo "🚀 Submitting CodeBuild job for ${PROJECT_NAME}"
|
|
14
|
+
echo " Deployment config: ${DEPLOYMENT_CONFIG}"
|
|
15
|
+
echo " Region: ${AWS_REGION}"
|
|
16
|
+
echo " Compute type: ${CODEBUILD_COMPUTE_TYPE}"
|
|
17
|
+
echo " ECR repository: ${ECR_REPOSITORY_NAME}"
|
|
18
|
+
|
|
19
|
+
# Validate AWS credentials
|
|
20
|
+
echo "🔍 Validating AWS credentials..."
|
|
21
|
+
if ! aws sts get-caller-identity &> /dev/null; then
|
|
22
|
+
echo "❌ AWS credentials not configured"
|
|
23
|
+
echo " Run: aws configure"
|
|
24
|
+
echo " Or set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables"
|
|
25
|
+
exit 4
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
# Get AWS account ID
|
|
29
|
+
AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
|
|
30
|
+
if [ -z "$AWS_ACCOUNT_ID" ]; then
|
|
31
|
+
echo "❌ Failed to get AWS account ID"
|
|
32
|
+
exit 4
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
echo "✅ AWS credentials validated (Account: ${AWS_ACCOUNT_ID})"
|
|
36
|
+
|
|
37
|
+
# Create ECR repository if it doesn't exist
|
|
38
|
+
echo "📦 Checking ECR repository..."
|
|
39
|
+
if ! aws ecr describe-repositories --repository-names "${ECR_REPOSITORY_NAME}" --region "${AWS_REGION}" >/dev/null 2>&1; then
|
|
40
|
+
echo "📦 Creating shared ECR repository: ${ECR_REPOSITORY_NAME}"
|
|
41
|
+
aws ecr create-repository --repository-name "${ECR_REPOSITORY_NAME}" --region "${AWS_REGION}"
|
|
42
|
+
echo "✅ ECR repository created successfully"
|
|
43
|
+
echo "ℹ️ This repository will be shared by all ML container projects"
|
|
44
|
+
else
|
|
45
|
+
echo "✅ ECR repository already exists: ${ECR_REPOSITORY_NAME}"
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# Create CodeBuild service role if it doesn't exist
|
|
49
|
+
ROLE_NAME="${CODEBUILD_PROJECT_NAME}-service-role"
|
|
50
|
+
echo "🔐 Checking CodeBuild service role..."
|
|
51
|
+
if ! aws iam get-role --role-name "${ROLE_NAME}" >/dev/null 2>&1; then
|
|
52
|
+
echo "🔐 Creating CodeBuild service role: ${ROLE_NAME}"
|
|
53
|
+
|
|
54
|
+
# Create trust policy
|
|
55
|
+
cat > /tmp/codebuild-trust-policy.json << EOF
|
|
56
|
+
{
|
|
57
|
+
"Version": "2012-10-17",
|
|
58
|
+
"Statement": [
|
|
59
|
+
{
|
|
60
|
+
"Effect": "Allow",
|
|
61
|
+
"Principal": {
|
|
62
|
+
"Service": "codebuild.amazonaws.com"
|
|
63
|
+
},
|
|
64
|
+
"Action": "sts:AssumeRole"
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
EOF
|
|
69
|
+
|
|
70
|
+
# Create the role
|
|
71
|
+
aws iam create-role \
|
|
72
|
+
--role-name "${ROLE_NAME}" \
|
|
73
|
+
--assume-role-policy-document file:///tmp/codebuild-trust-policy.json \
|
|
74
|
+
--description "Service role for CodeBuild project ${CODEBUILD_PROJECT_NAME}"
|
|
75
|
+
|
|
76
|
+
# Create and attach policy
|
|
77
|
+
cat > /tmp/codebuild-policy.json << EOF
|
|
78
|
+
{
|
|
79
|
+
"Version": "2012-10-17",
|
|
80
|
+
"Statement": [
|
|
81
|
+
{
|
|
82
|
+
"Effect": "Allow",
|
|
83
|
+
"Action": [
|
|
84
|
+
"logs:CreateLogGroup",
|
|
85
|
+
"logs:CreateLogStream",
|
|
86
|
+
"logs:PutLogEvents"
|
|
87
|
+
],
|
|
88
|
+
"Resource": "arn:aws:logs:${AWS_REGION}:${AWS_ACCOUNT_ID}:log-group:/aws/codebuild/${CODEBUILD_PROJECT_NAME}*"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"Effect": "Allow",
|
|
92
|
+
"Action": [
|
|
93
|
+
"ecr:BatchCheckLayerAvailability",
|
|
94
|
+
"ecr:GetDownloadUrlForLayer",
|
|
95
|
+
"ecr:BatchGetImage",
|
|
96
|
+
"ecr:GetAuthorizationToken",
|
|
97
|
+
"ecr:PutImage",
|
|
98
|
+
"ecr:InitiateLayerUpload",
|
|
99
|
+
"ecr:UploadLayerPart",
|
|
100
|
+
"ecr:CompleteLayerUpload"
|
|
101
|
+
],
|
|
102
|
+
"Resource": "*"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"Effect": "Allow",
|
|
106
|
+
"Action": [
|
|
107
|
+
"s3:GetObject",
|
|
108
|
+
"s3:GetObjectVersion"
|
|
109
|
+
],
|
|
110
|
+
"Resource": [
|
|
111
|
+
"arn:aws:s3:::codebuild-source-${AWS_ACCOUNT_ID}-${AWS_REGION}/*"
|
|
112
|
+
]
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"Effect": "Allow",
|
|
116
|
+
"Action": [
|
|
117
|
+
"s3:ListBucket"
|
|
118
|
+
],
|
|
119
|
+
"Resource": [
|
|
120
|
+
"arn:aws:s3:::codebuild-source-${AWS_ACCOUNT_ID}-${AWS_REGION}"
|
|
121
|
+
]
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
}
|
|
125
|
+
EOF
|
|
126
|
+
|
|
127
|
+
aws iam put-role-policy \
|
|
128
|
+
--role-name "${ROLE_NAME}" \
|
|
129
|
+
--policy-name CodeBuildServicePolicy \
|
|
130
|
+
--policy-document file:///tmp/codebuild-policy.json
|
|
131
|
+
|
|
132
|
+
# Clean up temporary files
|
|
133
|
+
rm -f /tmp/codebuild-trust-policy.json /tmp/codebuild-policy.json
|
|
134
|
+
|
|
135
|
+
echo "✅ CodeBuild service role created successfully"
|
|
136
|
+
|
|
137
|
+
# Record IAM role in manifest (non-blocking)
|
|
138
|
+
ROLE_ARN="arn:aws:iam::${AWS_ACCOUNT_ID}:role/${ROLE_NAME}"
|
|
139
|
+
./do/manifest add \
|
|
140
|
+
--type iam-role \
|
|
141
|
+
--id "${ROLE_ARN}" \
|
|
142
|
+
--project "${PROJECT_NAME}" \
|
|
143
|
+
--meta "{\"roleName\":\"${ROLE_NAME}\",\"region\":\"${AWS_REGION}\"}" \
|
|
144
|
+
2>/dev/null || true
|
|
145
|
+
|
|
146
|
+
# Wait for role to propagate
|
|
147
|
+
echo "⏳ Waiting for IAM role to propagate..."
|
|
148
|
+
sleep 10
|
|
149
|
+
else
|
|
150
|
+
echo "✅ CodeBuild service role already exists"
|
|
151
|
+
fi
|
|
152
|
+
|
|
153
|
+
# Create CodeBuild project if it doesn't exist
|
|
154
|
+
echo "🏗️ Checking CodeBuild project..."
|
|
155
|
+
PROJECT_EXISTS=$(aws codebuild batch-get-projects --names "${CODEBUILD_PROJECT_NAME}" --region "${AWS_REGION}" --query 'projects[0].name' --output text 2>/dev/null)
|
|
156
|
+
if [ "$PROJECT_EXISTS" = "None" ] || [ -z "$PROJECT_EXISTS" ] || [ "$PROJECT_EXISTS" = "null" ]; then
|
|
157
|
+
echo "🏗️ Creating CodeBuild project: ${CODEBUILD_PROJECT_NAME}"
|
|
158
|
+
|
|
159
|
+
# Create project configuration as JSON
|
|
160
|
+
cat > /tmp/codebuild-project.json << EOF
|
|
161
|
+
{
|
|
162
|
+
"name": "${CODEBUILD_PROJECT_NAME}",
|
|
163
|
+
"description": "Build project for ${PROJECT_NAME} ML container (${CODEBUILD_COMPUTE_TYPE})",
|
|
164
|
+
"source": {
|
|
165
|
+
"type": "NO_SOURCE",
|
|
166
|
+
"buildspec": "version: 0.2\n\nenv:\n variables:\n AWS_DEFAULT_REGION: ${AWS_REGION}\n AWS_ACCOUNT_ID: \"\"\n ECR_REPOSITORY_NAME: \"${ECR_REPOSITORY_NAME}\"\n PROJECT_NAME: \"${PROJECT_NAME}\"\n IMAGE_TAG: \"latest\"\n\nphases:\n pre_build:\n commands:\n - echo Logging in to Amazon ECR...\n - AWS_ACCOUNT_ID=\$(aws sts get-caller-identity --query Account --output text)\n - aws ecr get-login-password --region \$AWS_DEFAULT_REGION | docker login --username AWS --password-stdin \$AWS_ACCOUNT_ID.dkr.ecr.\$AWS_DEFAULT_REGION.amazonaws.com\n - echo Authenticating with AWS Deep Learning Container ECR...\n - aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 763104351884.dkr.ecr.us-east-1.amazonaws.com\n - REPOSITORY_URI=\$AWS_ACCOUNT_ID.dkr.ecr.\$AWS_DEFAULT_REGION.amazonaws.com/\$ECR_REPOSITORY_NAME\n - IMAGE_TAG=\${CODEBUILD_RESOLVED_SOURCE_VERSION:-latest}\n - PROJECT_TAG=\"\$PROJECT_NAME-\$(date +%Y%m%d-%H%M%S)\"\n - echo Repository URI is \$REPOSITORY_URI\n - echo Project tag is \$PROJECT_TAG\n - echo Image tag is \$IMAGE_TAG\n on-failure: ABORT\n build:\n commands:\n - echo Build started on \`date\`\n - echo Building the Docker image for project \$PROJECT_NAME...\n - docker build -t \$REPOSITORY_URI:\$PROJECT_TAG .\n - docker tag \$REPOSITORY_URI:\$PROJECT_TAG \$REPOSITORY_URI:\$PROJECT_NAME-latest\n - docker tag \$REPOSITORY_URI:\$PROJECT_TAG \$REPOSITORY_URI:latest\n - echo Build completed on \`date\`\n on-failure: ABORT\n post_build:\n commands:\n - echo Post-build started on \`date\`\n - echo Pushing the Docker images for project \$PROJECT_NAME...\n - docker push \$REPOSITORY_URI:\$PROJECT_TAG || (echo \"Failed to push project tag \$PROJECT_TAG\" && exit 1)\n - docker push \$REPOSITORY_URI:\$PROJECT_NAME-latest || (echo \"Failed to push project latest tag\" && exit 1)\n - docker push \$REPOSITORY_URI:latest || (echo \"Failed to push latest tag\" && exit 1)\n - echo Successfully pushed images to ECR repository \$ECR_REPOSITORY_NAME\n - echo \"Available tags:\"\n - echo \" - \$PROJECT_TAG (timestamped build)\"\n - echo \" - \$PROJECT_NAME-latest (project latest)\"\n - echo \" - latest (global latest)\"\n - echo Writing image definitions file...\n - printf '[{\"name\":\"%s\",\"imageUri\":\"%s\"}]' \$PROJECT_NAME \$REPOSITORY_URI:\$PROJECT_TAG > imagedefinitions.json\n - echo Post-build completed on \`date\`\n\nartifacts:\n files:\n - imagedefinitions.json\n name: ${PROJECT_NAME}-artifacts"
|
|
167
|
+
},
|
|
168
|
+
"artifacts": {
|
|
169
|
+
"type": "NO_ARTIFACTS"
|
|
170
|
+
},
|
|
171
|
+
"environment": {
|
|
172
|
+
"type": "LINUX_CONTAINER",
|
|
173
|
+
"image": "aws/codebuild/amazonlinux2-x86_64-standard:3.0",
|
|
174
|
+
"computeType": "${CODEBUILD_COMPUTE_TYPE}",
|
|
175
|
+
"privilegedMode": true
|
|
176
|
+
},
|
|
177
|
+
"serviceRole": "arn:aws:iam::${AWS_ACCOUNT_ID}:role/${ROLE_NAME}"
|
|
178
|
+
}
|
|
179
|
+
EOF
|
|
180
|
+
|
|
181
|
+
# Create project using JSON input
|
|
182
|
+
aws codebuild create-project \
|
|
183
|
+
--region "${AWS_REGION}" \
|
|
184
|
+
--cli-input-json file:///tmp/codebuild-project.json > /tmp/codebuild-create-output.json 2>&1
|
|
185
|
+
|
|
186
|
+
CREATE_EXIT_CODE=$?
|
|
187
|
+
|
|
188
|
+
if [ $CREATE_EXIT_CODE -eq 0 ]; then
|
|
189
|
+
echo "✅ CodeBuild project created successfully"
|
|
190
|
+
if [ -f /tmp/codebuild-create-output.json ]; then
|
|
191
|
+
PROJECT_ARN=$(cat /tmp/codebuild-create-output.json | jq -r '.project.arn // "N/A"' 2>/dev/null || echo "N/A")
|
|
192
|
+
echo " Project ARN: $PROJECT_ARN"
|
|
193
|
+
fi
|
|
194
|
+
|
|
195
|
+
# Wait for project to be available
|
|
196
|
+
echo "⏳ Waiting for CodeBuild project to be available..."
|
|
197
|
+
sleep 5
|
|
198
|
+
|
|
199
|
+
# Verify project was created
|
|
200
|
+
VERIFY_PROJECT=$(aws codebuild batch-get-projects --names "${CODEBUILD_PROJECT_NAME}" --region "${AWS_REGION}" --query 'projects[0].name' --output text 2>/dev/null)
|
|
201
|
+
if [ "$VERIFY_PROJECT" = "None" ] || [ -z "$VERIFY_PROJECT" ] || [ "$VERIFY_PROJECT" = "null" ]; then
|
|
202
|
+
echo "❌ Project creation verification failed"
|
|
203
|
+
echo " Create output:"
|
|
204
|
+
cat /tmp/codebuild-create-output.json 2>/dev/null || echo " No output file"
|
|
205
|
+
rm -f /tmp/codebuild-create-output.json /tmp/codebuild-project.json
|
|
206
|
+
exit 1
|
|
207
|
+
else
|
|
208
|
+
echo "✅ Project creation verified: $VERIFY_PROJECT"
|
|
209
|
+
fi
|
|
210
|
+
|
|
211
|
+
# Record CodeBuild project in manifest (non-blocking)
|
|
212
|
+
if [ "$PROJECT_ARN" != "N/A" ] && [ -n "$PROJECT_ARN" ]; then
|
|
213
|
+
./do/manifest add \
|
|
214
|
+
--type codebuild-project \
|
|
215
|
+
--id "${PROJECT_ARN}" \
|
|
216
|
+
--project "${PROJECT_NAME}" \
|
|
217
|
+
--meta "{\"projectName\":\"${CODEBUILD_PROJECT_NAME}\",\"region\":\"${AWS_REGION}\"}" \
|
|
218
|
+
2>/dev/null || true
|
|
219
|
+
fi
|
|
220
|
+
else
|
|
221
|
+
echo "❌ Failed to create CodeBuild project: ${CODEBUILD_PROJECT_NAME} (exit code: $CREATE_EXIT_CODE)"
|
|
222
|
+
echo " Error output:"
|
|
223
|
+
cat /tmp/codebuild-create-output.json 2>/dev/null || echo " No error output available"
|
|
224
|
+
echo ""
|
|
225
|
+
echo " Please check:"
|
|
226
|
+
echo " 1. IAM permissions for CodeBuild operations"
|
|
227
|
+
echo " 2. Service role ARN: arn:aws:iam::${AWS_ACCOUNT_ID}:role/${ROLE_NAME}"
|
|
228
|
+
echo " 3. AWS region: ${AWS_REGION}"
|
|
229
|
+
echo " 4. Project name format: ${CODEBUILD_PROJECT_NAME}"
|
|
230
|
+
echo " 5. Network connectivity to AWS services"
|
|
231
|
+
rm -f /tmp/codebuild-create-output.json /tmp/codebuild-project.json
|
|
232
|
+
exit 1
|
|
233
|
+
fi
|
|
234
|
+
|
|
235
|
+
# Clean up output files
|
|
236
|
+
rm -f /tmp/codebuild-create-output.json /tmp/codebuild-project.json
|
|
237
|
+
else
|
|
238
|
+
echo "✅ CodeBuild project already exists: $PROJECT_EXISTS"
|
|
239
|
+
fi
|
|
240
|
+
|
|
241
|
+
# Upload source code to S3
|
|
242
|
+
echo "📁 Uploading source code from current directory..."
|
|
243
|
+
|
|
244
|
+
# Create a temporary zip file with the current directory contents
|
|
245
|
+
TEMP_ZIP="/tmp/${PROJECT_NAME}-source.zip"
|
|
246
|
+
echo "📦 Creating source archive..."
|
|
247
|
+
|
|
248
|
+
# Create zip file excluding unnecessary files
|
|
249
|
+
zip -r "$TEMP_ZIP" . \
|
|
250
|
+
-x "*.git*" \
|
|
251
|
+
-x "*node_modules*" \
|
|
252
|
+
-x "*.DS_Store*" \
|
|
253
|
+
-x "*__pycache__*" \
|
|
254
|
+
-x "*.pyc" \
|
|
255
|
+
-x "*/.pytest_cache/*" \
|
|
256
|
+
-x "*/test/*" \
|
|
257
|
+
-x "*/tests/*" \
|
|
258
|
+
>/dev/null 2>&1
|
|
259
|
+
|
|
260
|
+
if [ ! -f "$TEMP_ZIP" ]; then
|
|
261
|
+
echo "❌ Failed to create source archive"
|
|
262
|
+
exit 1
|
|
263
|
+
fi
|
|
264
|
+
|
|
265
|
+
echo "✅ Source archive created: $(du -h "$TEMP_ZIP" | cut -f1)"
|
|
266
|
+
|
|
267
|
+
# Upload source to S3 for CodeBuild
|
|
268
|
+
S3_BUCKET="codebuild-source-${AWS_ACCOUNT_ID}-${AWS_REGION}"
|
|
269
|
+
S3_KEY="${PROJECT_NAME}/source-$(date +%Y%m%d-%H%M%S).zip"
|
|
270
|
+
|
|
271
|
+
# Create S3 bucket if it doesn't exist
|
|
272
|
+
if ! aws s3api head-bucket --bucket "$S3_BUCKET" --region "${AWS_REGION}" >/dev/null 2>&1; then
|
|
273
|
+
echo "📦 Creating S3 bucket for CodeBuild source: $S3_BUCKET"
|
|
274
|
+
if [ "${AWS_REGION}" = "us-east-1" ]; then
|
|
275
|
+
aws s3api create-bucket --bucket "$S3_BUCKET" --region "${AWS_REGION}"
|
|
276
|
+
else
|
|
277
|
+
aws s3api create-bucket --bucket "$S3_BUCKET" --region "${AWS_REGION}" --create-bucket-configuration LocationConstraint="${AWS_REGION}"
|
|
278
|
+
fi
|
|
279
|
+
fi
|
|
280
|
+
|
|
281
|
+
# Upload source to S3
|
|
282
|
+
echo "📤 Uploading source to S3..."
|
|
283
|
+
aws s3 cp "$TEMP_ZIP" "s3://$S3_BUCKET/$S3_KEY" --region "${AWS_REGION}"
|
|
284
|
+
|
|
285
|
+
# Record S3 object in manifest (non-blocking)
|
|
286
|
+
./do/manifest add \
|
|
287
|
+
--type s3-object \
|
|
288
|
+
--id "s3://${S3_BUCKET}/${S3_KEY}" \
|
|
289
|
+
--project "${PROJECT_NAME}" \
|
|
290
|
+
--meta "{\"bucket\":\"${S3_BUCKET}\",\"key\":\"${S3_KEY}\",\"region\":\"${AWS_REGION}\"}" \
|
|
291
|
+
2>/dev/null || true
|
|
292
|
+
|
|
293
|
+
# Clean up local zip file
|
|
294
|
+
rm -f "$TEMP_ZIP"
|
|
295
|
+
|
|
296
|
+
# Start CodeBuild job
|
|
297
|
+
echo "🚀 Starting CodeBuild job..."
|
|
298
|
+
echo " Project: ${CODEBUILD_PROJECT_NAME}"
|
|
299
|
+
echo " S3 source: s3://$S3_BUCKET/$S3_KEY"
|
|
300
|
+
|
|
301
|
+
# Double-check project exists before starting build
|
|
302
|
+
FINAL_CHECK=$(aws codebuild batch-get-projects --names "${CODEBUILD_PROJECT_NAME}" --region "${AWS_REGION}" --query 'projects[0].name' --output text 2>/dev/null)
|
|
303
|
+
if [ "$FINAL_CHECK" = "None" ] || [ -z "$FINAL_CHECK" ] || [ "$FINAL_CHECK" = "null" ]; then
|
|
304
|
+
echo "❌ CodeBuild project not found before starting build: ${CODEBUILD_PROJECT_NAME}"
|
|
305
|
+
echo " Available projects in region ${AWS_REGION}:"
|
|
306
|
+
aws codebuild list-projects --region "${AWS_REGION}" --query 'projects' --output table 2>/dev/null || echo " Could not list projects"
|
|
307
|
+
exit 1
|
|
308
|
+
fi
|
|
309
|
+
|
|
310
|
+
# Start build
|
|
311
|
+
aws codebuild start-build \
|
|
312
|
+
--project-name "${CODEBUILD_PROJECT_NAME}" \
|
|
313
|
+
--source-type-override S3 \
|
|
314
|
+
--source-location-override "$S3_BUCKET/$S3_KEY" \
|
|
315
|
+
--region "${AWS_REGION}" \
|
|
316
|
+
--query 'build.id' \
|
|
317
|
+
--output text > /tmp/build-id.txt 2>&1
|
|
318
|
+
|
|
319
|
+
START_EXIT_CODE=$?
|
|
320
|
+
BUILD_ID=""
|
|
321
|
+
|
|
322
|
+
if [ $START_EXIT_CODE -eq 0 ]; then
|
|
323
|
+
BUILD_ID=$(cat /tmp/build-id.txt)
|
|
324
|
+
rm -f /tmp/build-id.txt
|
|
325
|
+
else
|
|
326
|
+
echo "❌ Failed to start build (exit code: $START_EXIT_CODE)"
|
|
327
|
+
echo " Error output:"
|
|
328
|
+
cat /tmp/build-id.txt 2>/dev/null || echo " No error output available"
|
|
329
|
+
rm -f /tmp/build-id.txt
|
|
330
|
+
exit 1
|
|
331
|
+
fi
|
|
332
|
+
|
|
333
|
+
# Check if BUILD_ID is valid
|
|
334
|
+
if [ -z "$BUILD_ID" ] || [ "$BUILD_ID" = "None" ] || [ "$BUILD_ID" = "null" ]; then
|
|
335
|
+
echo "❌ Failed to start CodeBuild job"
|
|
336
|
+
echo " Debugging information:"
|
|
337
|
+
echo " Project name: ${CODEBUILD_PROJECT_NAME}"
|
|
338
|
+
echo " Region: ${AWS_REGION}"
|
|
339
|
+
echo " Account ID: ${AWS_ACCOUNT_ID}"
|
|
340
|
+
echo " S3 Source: s3://$S3_BUCKET/$S3_KEY"
|
|
341
|
+
exit 1
|
|
342
|
+
fi
|
|
343
|
+
|
|
344
|
+
echo "✅ Build started with ID: $BUILD_ID"
|
|
345
|
+
echo "📊 Monitor build at: https://${AWS_REGION}.console.aws.amazon.com/codesuite/codebuild/projects/${CODEBUILD_PROJECT_NAME}/build/$BUILD_ID"
|
|
346
|
+
echo ""
|
|
347
|
+
echo "⏳ Monitoring build progress..."
|
|
348
|
+
|
|
349
|
+
# Monitor build status
|
|
350
|
+
PREVIOUS_STATUS=""
|
|
351
|
+
while true; do
|
|
352
|
+
BUILD_INFO=$(aws codebuild batch-get-builds \
|
|
353
|
+
--ids "$BUILD_ID" \
|
|
354
|
+
--region "${AWS_REGION}" \
|
|
355
|
+
--query 'builds[0].[buildStatus,currentPhase]' \
|
|
356
|
+
--output text)
|
|
357
|
+
|
|
358
|
+
# Parse status
|
|
359
|
+
BUILD_STATUS=$(echo "$BUILD_INFO" | awk '{print $1}')
|
|
360
|
+
CURRENT_PHASE=$(echo "$BUILD_INFO" | awk '{print $2}')
|
|
361
|
+
|
|
362
|
+
# Only print status changes
|
|
363
|
+
CURRENT_STATUS="$BUILD_STATUS:$CURRENT_PHASE"
|
|
364
|
+
if [ "$CURRENT_STATUS" != "$PREVIOUS_STATUS" ]; then
|
|
365
|
+
echo "📋 Build status: $BUILD_STATUS | Phase: $CURRENT_PHASE"
|
|
366
|
+
PREVIOUS_STATUS="$CURRENT_STATUS"
|
|
367
|
+
fi
|
|
368
|
+
|
|
369
|
+
# Check for completion
|
|
370
|
+
if [[ "$BUILD_STATUS" == "SUCCEEDED"* ]]; then
|
|
371
|
+
echo ""
|
|
372
|
+
echo "✅ Build completed successfully!"
|
|
373
|
+
echo "🐳 Docker image available at:"
|
|
374
|
+
echo " ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${ECR_REPOSITORY_NAME}:${PROJECT_NAME}-latest"
|
|
375
|
+
echo " ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com/${ECR_REPOSITORY_NAME}:latest"
|
|
376
|
+
echo ""
|
|
377
|
+
echo "Next steps:"
|
|
378
|
+
echo " • Deploy to SageMaker: ./do/deploy"
|
|
379
|
+
echo " • Or use the ECR image URI in your own deployment process"
|
|
380
|
+
exit 0
|
|
381
|
+
elif [[ "$BUILD_STATUS" == "FAILED"* ]] || [[ "$BUILD_STATUS" == "FAULT"* ]] || [[ "$BUILD_STATUS" == "STOPPED"* ]] || [[ "$BUILD_STATUS" == "TIMED_OUT"* ]]; then
|
|
382
|
+
echo ""
|
|
383
|
+
echo "❌ Build failed with status: $BUILD_STATUS"
|
|
384
|
+
echo ""
|
|
385
|
+
echo "📋 Fetching build logs..."
|
|
386
|
+
|
|
387
|
+
# Try to get build logs
|
|
388
|
+
LOG_GROUP="/aws/codebuild/${CODEBUILD_PROJECT_NAME}"
|
|
389
|
+
LOG_STREAM=$(aws logs describe-log-streams \
|
|
390
|
+
--log-group-name "$LOG_GROUP" \
|
|
391
|
+
--order-by LastEventTime \
|
|
392
|
+
--descending \
|
|
393
|
+
--max-items 1 \
|
|
394
|
+
--region "${AWS_REGION}" \
|
|
395
|
+
--query 'logStreams[0].logStreamName' \
|
|
396
|
+
--output text 2>/dev/null || echo "")
|
|
397
|
+
|
|
398
|
+
if [ -n "$LOG_STREAM" ] && [ "$LOG_STREAM" != "None" ]; then
|
|
399
|
+
echo "Recent build logs:"
|
|
400
|
+
echo "=================="
|
|
401
|
+
aws logs get-log-events \
|
|
402
|
+
--log-group-name "$LOG_GROUP" \
|
|
403
|
+
--log-stream-name "$LOG_STREAM" \
|
|
404
|
+
--region "${AWS_REGION}" \
|
|
405
|
+
--query 'events[-20:].message' \
|
|
406
|
+
--output text 2>/dev/null || echo "Could not retrieve logs"
|
|
407
|
+
else
|
|
408
|
+
echo "Could not retrieve build logs. Check the CodeBuild console for details."
|
|
409
|
+
fi
|
|
410
|
+
|
|
411
|
+
echo ""
|
|
412
|
+
echo "🔍 For detailed logs, visit: https://${AWS_REGION}.console.aws.amazon.com/codesuite/codebuild/projects/${CODEBUILD_PROJECT_NAME}/build/$BUILD_ID"
|
|
413
|
+
exit 1
|
|
414
|
+
fi
|
|
415
|
+
|
|
416
|
+
sleep 30
|
|
417
|
+
done
|