55 version :
66 description : The version to tag the release with, e.g., 1.2.0
77 required : true
8+ aws_region :
9+ description : ' Deploy lambda layer to aws regions'
10+ required : true
11+ default : ' us-east-1, us-east-2, us-west-1, us-west-2, ap-south-1, ap-northeast-3, ap-northeast-2, ap-southeast-1, ap-southeast-2, ap-northeast-1, ca-central-1, eu-central-1, eu-west-1, eu-west-2, eu-west-3, eu-north-1, sa-east-1, af-south-1, ap-east-1, ap-south-2, ap-southeast-3, ap-southeast-4, eu-central-2, eu-south-1, eu-south-2, il-central-1, me-central-1, me-south-1, ap-southeast-5, ap-southeast-7, mx-central-1, ca-west-1, cn-north-1, cn-northwest-1'
812
913env :
1014 AWS_DEFAULT_REGION : us-east-1
1519 RELEASE_PRIVATE_REGISTRY : 020628701572.dkr.ecr.us-west-2.amazonaws.com
1620 PACKAGE_NAME : aws-opentelemetry-distro
1721 ARTIFACT_NAME : aws_opentelemetry_distro-${{ github.event.inputs.version }}-py3-none-any.whl
22+ # Legacy list of commercial regions to deploy to. New regions should NOT be added here, and instead should be added to the `aws_region` default input to the workflow.
23+ LEGACY_COMMERCIAL_REGIONS : us-east-1, us-east-2, us-west-1, us-west-2, ap-south-1, ap-northeast-3, ap-northeast-2, ap-southeast-1, ap-southeast-2, ap-northeast-1, ca-central-1, eu-central-1, eu-west-1, eu-west-2, eu-west-3, eu-north-1, sa-east-1
24+ LAYER_NAME : AWSOpenTelemetryDistroPython
1825
1926permissions :
2027 id-token : write
2128 contents : write
2229
2330jobs :
24- build :
31+ build-sdk :
2532 environment : Release
2633 runs-on : ubuntu-latest
2734 steps :
6067 # release the artifacts. adot java for reference:
6168 # https://github.com/aws-observability/aws-otel-java-instrumentation/tree/93870a550ac30988fbdd5d3bf1e8f9f1b37916f5/smoke-tests
6269
70+ - name : Upload SDK artifact
71+ uses : actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
72+ with :
73+ name : ${{ env.ARTIFACT_NAME }}
74+ path : dist/${{ env.ARTIFACT_NAME }}
75+
76+ build-layer :
77+ needs : build-sdk
78+ runs-on : ubuntu-latest
79+ outputs :
80+ aws_regions_json : ${{ steps.set-matrix.outputs.aws_regions_json }}
81+ steps :
82+ - name : Set up regions matrix
83+ id : set-matrix
84+ run : |
85+ IFS=',' read -ra REGIONS <<< "${{ github.event.inputs.aws_region }}"
86+ MATRIX="["
87+ for region in "${REGIONS[@]}"; do
88+ trimmed_region=$(echo "$region" | xargs)
89+ MATRIX+="\"$trimmed_region\","
90+ done
91+ MATRIX="${MATRIX%,}]"
92+ echo ${MATRIX}
93+ echo "aws_regions_json=${MATRIX}" >> $GITHUB_OUTPUT
94+ - name : Checkout Repo @ SHA - ${{ github.sha }}
95+ uses : actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
96+ - uses : actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
97+ with :
98+ python-version : ' 3.x'
99+ - name : Build layers
100+ working-directory : lambda-layer/src
101+ run : |
102+ ./build-lambda-layer.sh
103+ pip install tox
104+ tox
105+ - name : upload layer
106+ uses : actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
107+ with :
108+ name : layer.zip
109+ path : lambda-layer/src/build/aws-opentelemetry-python-layer.zip
110+
111+ publish-sdk :
112+ needs : [build-sdk, build-layer]
113+ runs-on : ubuntu-latest
114+ steps :
115+ - name : Checkout Repo @ SHA - ${{ github.sha }}
116+ uses : actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
117+
63118 - name : Configure AWS credentials for PyPI secrets
64119 uses : aws-actions/configure-aws-credentials@a03048d87541d1d9fcf2ecf528a4a65ba9bd7838 # v5.0.0
65120 with :
@@ -102,20 +157,25 @@ jobs:
102157 - name : Install twine
103158 run : pip install twine
104159
160+ - name : Download SDK artifact
161+ uses : actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
162+ with :
163+ name : ${{ env.ARTIFACT_NAME }}
164+
105165 - name : Publish to TestPyPI
106166 env :
107167 TWINE_USERNAME : ' __token__'
108168 TWINE_PASSWORD : ${{ env.TEST_PYPI_TOKEN_API_TOKEN }}
109169 run : |
110- twine upload --repository testpypi --skip-existing --verbose dist/ ${{ env.ARTIFACT_NAME }}
170+ twine upload --repository testpypi --skip-existing --verbose ${{ env.ARTIFACT_NAME }}
111171
112172 # Publish to prod PyPI
113173 - name : Publish to PyPI
114174 env :
115175 TWINE_USERNAME : ' __token__'
116176 TWINE_PASSWORD : ${{ env.PROD_PYPI_TOKEN_API_TOKEN }}
117177 run : |
118- twine upload --skip-existing --verbose dist/ ${{ env.ARTIFACT_NAME }}
178+ twine upload --skip-existing --verbose ${{ env.ARTIFACT_NAME }}
119179
120180 # Publish to public ECR
121181 - name : Build and push public ECR image
@@ -138,29 +198,230 @@ jobs:
138198 platforms : linux/amd64,linux/arm64
139199 tags : |
140200 ${{ env.RELEASE_PRIVATE_REPOSITORY }}:v${{ github.event.inputs.version }}
201+
202+ publish-layer-prod :
203+ runs-on : ubuntu-latest
204+ needs : [build-layer, publish-sdk]
205+ strategy :
206+ matrix :
207+ aws_region : ${{ fromJson(needs.build-layer.outputs.aws_regions_json) }}
208+ steps :
209+ - name : role arn
210+ env :
211+ LEGACY_COMMERCIAL_REGIONS : ${{ env.LEGACY_COMMERCIAL_REGIONS }}
212+ run : |
213+ LEGACY_COMMERCIAL_REGIONS_ARRAY=(${LEGACY_COMMERCIAL_REGIONS//,/ })
214+ FOUND=false
215+ for REGION in "${LEGACY_COMMERCIAL_REGIONS_ARRAY[@]}"; do
216+ if [[ "$REGION" == "${{ matrix.aws_region }}" ]]; then
217+ FOUND=true
218+ break
219+ fi
220+ done
221+ if [ "$FOUND" = true ]; then
222+ echo "Found ${{ matrix.aws_region }} in LEGACY_COMMERCIAL_REGIONS"
223+ SECRET_KEY="LAMBDA_LAYER_RELEASE"
224+ else
225+ echo "Not found ${{ matrix.aws_region }} in LEGACY_COMMERCIAL_REGIONS"
226+ SECRET_KEY="${{ matrix.aws_region }}_LAMBDA_LAYER_RELEASE"
227+ fi
228+ SECRET_KEY=${SECRET_KEY//-/_}
229+ echo "SECRET_KEY=${SECRET_KEY}" >> $GITHUB_ENV
230+ - uses : aws-actions/configure-aws-credentials@a03048d87541d1d9fcf2ecf528a4a65ba9bd7838 # v5.0.0
231+ with :
232+ role-to-assume : ${{ secrets[env.SECRET_KEY] }}
233+ role-duration-seconds : 1200
234+ aws-region : ${{ matrix.aws_region }}
235+ - name : Get s3 bucket name for release
236+ run : |
237+ echo BUCKET_NAME=python-lambda-layer-${{ github.run_id }}-${{ matrix.aws_region }} | tee --append $GITHUB_ENV
238+ - name : download layer.zip
239+ uses : actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
240+ with :
241+ name : layer.zip
242+ - name : publish
243+ run : |
244+ aws s3 mb s3://${{ env.BUCKET_NAME }}
245+ aws s3 cp aws-opentelemetry-python-layer.zip s3://${{ env.BUCKET_NAME }}
246+ layerARN=$(
247+ aws lambda publish-layer-version \
248+ --layer-name ${{ env.LAYER_NAME }} \
249+ --content S3Bucket=${{ env.BUCKET_NAME }},S3Key=aws-opentelemetry-python-layer.zip \
250+ --compatible-runtimes python3.10 python3.11 python3.12 python3.13 \
251+ --compatible-architectures "arm64" "x86_64" \
252+ --license-info "Apache-2.0" \
253+ --description "AWS Distro of OpenTelemetry Lambda Layer for Python Runtime" \
254+ --query 'LayerVersionArn' \
255+ --output text
256+ )
257+ echo $layerARN
258+ echo "LAYER_ARN=${layerARN}" >> $GITHUB_ENV
259+ mkdir ${{ env.LAYER_NAME }}
260+ echo $layerARN > ${{ env.LAYER_NAME }}/${{ matrix.aws_region }}
261+ cat ${{ env.LAYER_NAME }}/${{ matrix.aws_region }}
262+ - name : public layer
263+ run : |
264+ layerVersion=$(
265+ aws lambda list-layer-versions \
266+ --layer-name ${{ env.LAYER_NAME }} \
267+ --query 'max_by(LayerVersions, &Version).Version'
268+ )
269+ aws lambda add-layer-version-permission \
270+ --layer-name ${{ env.LAYER_NAME }} \
271+ --version-number $layerVersion \
272+ --principal "*" \
273+ --statement-id publish \
274+ --action lambda:GetLayerVersion
275+ - name : upload layer arn artifact
276+ if : ${{ success() }}
277+ uses : actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
278+ with :
279+ name : ${{ env.LAYER_NAME }}-${{ matrix.aws_region }}
280+ path : ${{ env.LAYER_NAME }}/${{ matrix.aws_region }}
281+ - name : clean s3
282+ if : always()
283+ run : |
284+ aws s3 rb --force s3://${{ env.BUCKET_NAME }}
285+
286+ generate-lambda-release-note :
287+ runs-on : ubuntu-latest
288+ needs : publish-layer-prod
289+ outputs :
290+ layer-note : ${{ steps.layer-note.outputs.layer-note }}
291+ steps :
292+ - name : Checkout Repo @ SHA - ${{ github.sha }}
293+ uses : actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
294+ - uses : hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3.1.2
295+ - name : download layerARNs
296+ uses : actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
297+ with :
298+ pattern : ${{ env.LAYER_NAME }}-*
299+ path : ${{ env.LAYER_NAME }}
300+ merge-multiple : true
301+ - name : show layerARNs
302+ run : |
303+ for file in ${{ env.LAYER_NAME }}/*
304+ do
305+ echo $file
306+ cat $file
307+ done
308+ - name : generate layer-note
309+ id : layer-note
310+ working-directory : ${{ env.LAYER_NAME }}
311+ run : |
312+ echo "| Region | Layer ARN |" >> ../layer-note
313+ echo "| ---- | ---- |" >> ../layer-note
314+ for file in *
315+ do
316+ read arn < $file
317+ echo "| " $file " | " $arn " |" >> ../layer-note
318+ done
319+ cd ..
320+ {
321+ echo "layer-note<<EOF"
322+ cat layer-note
323+ echo "EOF"
324+ } >> $GITHUB_OUTPUT
325+ cat layer-note
326+ - name : generate tf layer
327+ working-directory : ${{ env.LAYER_NAME }}
328+ run : |
329+ echo "locals {" >> ../layer_arns.tf
330+ echo " sdk_layer_arns = {" >> ../layer_arns.tf
331+ for file in *
332+ do
333+ read arn < $file
334+ echo " \""$file"\" = \""$arn"\"" >> ../layer_arns.tf
335+ done
336+ cd ..
337+ echo " }" >> layer_arns.tf
338+ echo "}" >> layer_arns.tf
339+ terraform fmt layer_arns.tf
340+ cat layer_arns.tf
341+ - name : generate layer ARN constants for CDK
342+ working-directory : ${{ env.LAYER_NAME }}
343+ run : |
344+ echo "{" > ../layer_cdk
345+ for file in *; do
346+ read arn < "$file"
347+ echo " \"$file\": \"$arn\"," >> ../layer_cdk
348+ done
349+ echo "}" >> ../layer_cdk
350+ cat ../layer_cdk
351+
352+ publish-github :
353+ needs : generate-lambda-release-note
354+ runs-on : ubuntu-latest
355+ steps :
356+ - name : Checkout Repo @ SHA - ${{ github.sha }}
357+ uses : actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
358+
359+ - name : Download SDK artifact
360+ uses : actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
361+ with :
362+ name : ${{ env.ARTIFACT_NAME }}
363+
364+ - name : Download layer.zip artifact
365+ uses : actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
366+ with :
367+ name : layer.zip
141368
142- - name : Get SHA256 checksum of wheel file
143- id : get_sha256
369+ - name : Rename layer file
144370 run : |
145- shasum -a 256 dist/${{ env.ARTIFACT_NAME }} | sed "s|dist/||" > ${{ env.ARTIFACT_NAME }}.sha256
371+ cp aws-opentelemetry-python-layer.zip layer.zip
146372
147373 # Publish to GitHub releases
148374 - name : Create GH release
149375 id : create_release
150376 env :
151- GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
377+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
152378 run : |
153- # Download layer.zip from existing latest tagged SDK release note
154- LATEST_SDK_VERSION=$(gh release list --repo "aws-observability/aws-otel-python-instrumentation" --json tagName,isLatest -q 'map(select(.isLatest==true)) | .[0].tagName')
155- mkdir -p layer_artifact
156- gh release download "$LATEST_SDK_VERSION" --repo "aws-observability/aws-otel-python-instrumentation" --pattern "layer.zip" --dir layer_artifact
157- shasum -a 256 layer_artifact/layer.zip > layer_artifact/layer.zip.sha256
379+ # Extract all dependencies from pyproject.toml
380+ DEPS=$(python3 -c "
381+ import re
382+ with open('aws-opentelemetry-distro/pyproject.toml', 'r') as f:
383+ content = f.read()
384+ deps_match = re.search(r'dependencies\s*=\s*\[(.*?)\]', content, re.DOTALL)
385+ if deps_match:
386+ deps_content = deps_match.group(1)
387+ dep_lines = re.findall(r'\"([^\"]+)\"', deps_content)
388+ formatted_deps = []
389+ for dep_line in dep_lines:
390+ if ' == ' in dep_line:
391+ package, version = dep_line.split(' == ', 1)
392+ formatted_deps.append(f'- \`{package}\` - {version}')
393+ else:
394+ formatted_deps.append(f'- \`{dep_line}\`')
395+ print('\n'.join(formatted_deps))
396+ ")
397+
398+ # Create release notes
399+ cat > release_notes.md << EOF
400+ This release contains the following upstream components:
401+
402+ $DEPS
403+
404+ This release also publishes to public ECR and PyPi.
405+ * See ADOT Python auto-instrumentation Docker image v${{ github.event.inputs.version }} in our public ECR repository:
406+ https://gallery.ecr.aws/aws-observability/adot-autoinstrumentation-python
407+ * See version ${{ github.event.inputs.version }} in our PyPi repository:
408+ https://pypi.org/project/aws-opentelemetry-distro/
409+
410+ This release also includes the AWS OpenTelemetry Lambda Layer for Python version ${{ github.event.inputs.version }}-$(echo $GITHUB_SHA | cut -c1-7).
411+
412+ Lambda Layer ARNs:
413+ ${{ needs.generate-lambda-release-note.outputs.layer-note }}
414+ EOF
415+
416+ shasum -a 256 ${{ env.ARTIFACT_NAME }} > ${{ env.ARTIFACT_NAME }}.sha256
417+ shasum -a 256 layer.zip > layer.zip.sha256
158418
159419 gh release create --target "$GITHUB_REF_NAME" \
160420 --title "Release v${{ github.event.inputs.version }}" \
421+ --notes-file release_notes.md \
161422 --draft \
162423 "v${{ github.event.inputs.version }}" \
163- dist/ ${{ env.ARTIFACT_NAME }} \
424+ ${{ env.ARTIFACT_NAME }} \
164425 ${{ env.ARTIFACT_NAME }}.sha256 \
165- layer_artifact/ layer.zip \
166- layer_artifact/ layer.zip.sha256
426+ layer.zip \
427+ layer.zip.sha256
0 commit comments