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+ env :
85+ AWS_REGIONS : ${{ github.event.inputs.aws_region }}
86+ run : |
87+ IFS=',' read -ra REGIONS <<< "$AWS_REGIONS"
88+ MATRIX="["
89+ for region in "${REGIONS[@]}"; do
90+ trimmed_region=$(echo "$region" | xargs)
91+ MATRIX+="\"$trimmed_region\","
92+ done
93+ MATRIX="${MATRIX%,}]"
94+ echo ${MATRIX}
95+ echo "aws_regions_json=${MATRIX}" >> $GITHUB_OUTPUT
96+ - name : Checkout Repo @ SHA - ${{ github.sha }}
97+ uses : actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
98+ - uses : actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
99+ with :
100+ python-version : ' 3.x'
101+ - name : Build layers
102+ working-directory : lambda-layer/src
103+ run : |
104+ ./build-lambda-layer.sh
105+ pip install tox
106+ tox
107+ - name : upload layer
108+ uses : actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
109+ with :
110+ name : layer.zip
111+ path : lambda-layer/src/build/aws-opentelemetry-python-layer.zip
112+
113+ publish-sdk :
114+ needs : [build-sdk, build-layer]
115+ runs-on : ubuntu-latest
116+ steps :
117+ - name : Checkout Repo @ SHA - ${{ github.sha }}
118+ uses : actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
119+
63120 - name : Configure AWS credentials for PyPI secrets
64121 uses : aws-actions/configure-aws-credentials@a03048d87541d1d9fcf2ecf528a4a65ba9bd7838 # v5.0.0
65122 with :
@@ -102,20 +159,25 @@ jobs:
102159 - name : Install twine
103160 run : pip install twine
104161
162+ - name : Download SDK artifact
163+ uses : actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
164+ with :
165+ name : ${{ env.ARTIFACT_NAME }}
166+
105167 - name : Publish to TestPyPI
106168 env :
107169 TWINE_USERNAME : ' __token__'
108170 TWINE_PASSWORD : ${{ env.TEST_PYPI_TOKEN_API_TOKEN }}
109171 run : |
110- twine upload --repository testpypi --skip-existing --verbose dist/ ${{ env.ARTIFACT_NAME }}
172+ twine upload --repository testpypi --skip-existing --verbose ${{ env.ARTIFACT_NAME }}
111173
112174 # Publish to prod PyPI
113175 - name : Publish to PyPI
114176 env :
115177 TWINE_USERNAME : ' __token__'
116178 TWINE_PASSWORD : ${{ env.PROD_PYPI_TOKEN_API_TOKEN }}
117179 run : |
118- twine upload --skip-existing --verbose dist/ ${{ env.ARTIFACT_NAME }}
180+ twine upload --skip-existing --verbose ${{ env.ARTIFACT_NAME }}
119181
120182 # Publish to public ECR
121183 - name : Build and push public ECR image
@@ -138,29 +200,251 @@ jobs:
138200 platforms : linux/amd64,linux/arm64
139201 tags : |
140202 ${{ env.RELEASE_PRIVATE_REPOSITORY }}:v${{ github.event.inputs.version }}
203+
204+ publish-layer-prod :
205+ runs-on : ubuntu-latest
206+ needs : [build-layer, publish-sdk]
207+ strategy :
208+ matrix :
209+ aws_region : ${{ fromJson(needs.build-layer.outputs.aws_regions_json) }}
210+ steps :
211+ - name : role arn
212+ env :
213+ LEGACY_COMMERCIAL_REGIONS : ${{ env.LEGACY_COMMERCIAL_REGIONS }}
214+ run : |
215+ LEGACY_COMMERCIAL_REGIONS_ARRAY=(${LEGACY_COMMERCIAL_REGIONS//,/ })
216+ FOUND=false
217+ for REGION in "${LEGACY_COMMERCIAL_REGIONS_ARRAY[@]}"; do
218+ if [[ "$REGION" == "${{ matrix.aws_region }}" ]]; then
219+ FOUND=true
220+ break
221+ fi
222+ done
223+ if [ "$FOUND" = true ]; then
224+ echo "Found ${{ matrix.aws_region }} in LEGACY_COMMERCIAL_REGIONS"
225+ SECRET_KEY="LAMBDA_LAYER_RELEASE"
226+ else
227+ echo "Not found ${{ matrix.aws_region }} in LEGACY_COMMERCIAL_REGIONS"
228+ SECRET_KEY="${{ matrix.aws_region }}_LAMBDA_LAYER_RELEASE"
229+ fi
230+ SECRET_KEY=${SECRET_KEY//-/_}
231+ echo "SECRET_KEY=${SECRET_KEY}" >> $GITHUB_ENV
232+ - uses : aws-actions/configure-aws-credentials@a03048d87541d1d9fcf2ecf528a4a65ba9bd7838 # v5.0.0
233+ with :
234+ role-to-assume : ${{ secrets[env.SECRET_KEY] }}
235+ role-duration-seconds : 1200
236+ aws-region : ${{ matrix.aws_region }}
237+ - name : Get s3 bucket name for release
238+ run : |
239+ echo BUCKET_NAME=python-lambda-layer-${{ github.run_id }}-${{ matrix.aws_region }} | tee --append $GITHUB_ENV
240+ - name : download layer.zip
241+ uses : actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
242+ with :
243+ name : layer.zip
244+ - name : publish
245+ run : |
246+ aws s3 mb s3://${{ env.BUCKET_NAME }}
247+ aws s3 cp aws-opentelemetry-python-layer.zip s3://${{ env.BUCKET_NAME }}
248+ layerARN=$(
249+ aws lambda publish-layer-version \
250+ --layer-name ${{ env.LAYER_NAME }} \
251+ --content S3Bucket=${{ env.BUCKET_NAME }},S3Key=aws-opentelemetry-python-layer.zip \
252+ --compatible-runtimes python3.10 python3.11 python3.12 python3.13 \
253+ --compatible-architectures "arm64" "x86_64" \
254+ --license-info "Apache-2.0" \
255+ --description "AWS Distro of OpenTelemetry Lambda Layer for Python Runtime" \
256+ --query 'LayerVersionArn' \
257+ --output text
258+ )
259+ echo $layerARN
260+ echo "LAYER_ARN=${layerARN}" >> $GITHUB_ENV
261+ mkdir ${{ env.LAYER_NAME }}
262+ echo $layerARN > ${{ env.LAYER_NAME }}/${{ matrix.aws_region }}
263+ cat ${{ env.LAYER_NAME }}/${{ matrix.aws_region }}
264+ - name : public layer
265+ run : |
266+ layerVersion=$(
267+ aws lambda list-layer-versions \
268+ --layer-name ${{ env.LAYER_NAME }} \
269+ --query 'max_by(LayerVersions, &Version).Version'
270+ )
271+ aws lambda add-layer-version-permission \
272+ --layer-name ${{ env.LAYER_NAME }} \
273+ --version-number $layerVersion \
274+ --principal "*" \
275+ --statement-id publish \
276+ --action lambda:GetLayerVersion
277+ - name : upload layer arn artifact
278+ if : ${{ success() }}
279+ uses : actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
280+ with :
281+ name : ${{ env.LAYER_NAME }}-${{ matrix.aws_region }}
282+ path : ${{ env.LAYER_NAME }}/${{ matrix.aws_region }}
283+ - name : clean s3
284+ if : always()
285+ run : |
286+ aws s3 rb --force s3://${{ env.BUCKET_NAME }}
141287
142- - name : Get SHA256 checksum of wheel file
143- id : get_sha256
288+ generate-lambda-release-note :
289+ runs-on : ubuntu-latest
290+ needs : publish-layer-prod
291+ outputs :
292+ layer-note : ${{ steps.layer-note.outputs.layer-note }}
293+ steps :
294+ - name : Checkout Repo @ SHA - ${{ github.sha }}
295+ uses : actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
296+ - uses : hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3.1.2
297+ - name : download layerARNs
298+ uses : actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
299+ with :
300+ pattern : ${{ env.LAYER_NAME }}-*
301+ path : ${{ env.LAYER_NAME }}
302+ merge-multiple : true
303+ - name : show layerARNs
304+ run : |
305+ for file in ${{ env.LAYER_NAME }}/*
306+ do
307+ echo $file
308+ cat $file
309+ done
310+ - name : generate layer-note
311+ id : layer-note
312+ working-directory : ${{ env.LAYER_NAME }}
313+ run : |
314+ echo "| Region | Layer ARN |" >> ../layer-note
315+ echo "| ---- | ---- |" >> ../layer-note
316+ for file in *
317+ do
318+ read arn < $file
319+ echo "| " $file " | " $arn " |" >> ../layer-note
320+ done
321+ cd ..
322+ {
323+ echo "layer-note<<EOF"
324+ cat layer-note
325+ echo "EOF"
326+ } >> $GITHUB_OUTPUT
327+ cat layer-note
328+ - name : generate tf layer
329+ working-directory : ${{ env.LAYER_NAME }}
330+ run : |
331+ echo "locals {" >> ../layer_arns.tf
332+ echo " sdk_layer_arns = {" >> ../layer_arns.tf
333+ for file in *
334+ do
335+ read arn < $file
336+ echo " \""$file"\" = \""$arn"\"" >> ../layer_arns.tf
337+ done
338+ cd ..
339+ echo " }" >> layer_arns.tf
340+ echo "}" >> layer_arns.tf
341+ terraform fmt layer_arns.tf
342+ cat layer_arns.tf
343+ - name : generate layer ARN constants for CDK
344+ working-directory : ${{ env.LAYER_NAME }}
345+ run : |
346+ echo "{" > ../layer_cdk
347+ for file in *; do
348+ read arn < "$file"
349+ echo " \"$file\": \"$arn\"," >> ../layer_cdk
350+ done
351+ echo "}" >> ../layer_cdk
352+ cat ../layer_cdk
353+
354+ publish-github :
355+ needs : generate-lambda-release-note
356+ runs-on : ubuntu-latest
357+ steps :
358+ - name : Checkout Repo @ SHA - ${{ github.sha }}
359+ uses : actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
360+
361+ - name : Download SDK artifact
362+ uses : actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
363+ with :
364+ name : ${{ env.ARTIFACT_NAME }}
365+
366+ - name : Download layer.zip artifact
367+ uses : actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
368+ with :
369+ name : layer.zip
370+
371+ - name : Rename layer file
144372 run : |
145- shasum -a 256 dist/${{ env.ARTIFACT_NAME }} | sed "s|dist/||" > ${{ env.ARTIFACT_NAME }}.sha256
373+ cp aws-opentelemetry-python-layer.zip layer.zip
146374
147375 # Publish to GitHub releases
148376 - name : Create GH release
149377 id : create_release
150378 env :
151- GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
379+ GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }}
380+ VERSION : ${{ github.event.inputs.version }}
152381 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
382+ # Extract all dependencies from pyproject.toml
383+ DEPS=$(python3 -c "
384+ import re
385+ with open('aws-opentelemetry-distro/pyproject.toml', 'r') as f:
386+ content = f.read()
387+ deps_match = re.search(r'dependencies\s*=\s*\[(.*?)\]', content, re.DOTALL)
388+ if deps_match:
389+ deps_content = deps_match.group(1)
390+ dep_lines = re.findall(r'\"([^\"]+)\"', deps_content)
391+ formatted_deps = []
392+ for dep_line in dep_lines:
393+ if ' == ' in dep_line:
394+ package, version = dep_line.split(' == ', 1)
395+ formatted_deps.append(f'- \`{package}\` - {version}')
396+ else:
397+ formatted_deps.append(f'- \`{dep_line}\`')
398+ print('\n'.join(formatted_deps))
399+ ")
400+
401+ # Extract CHANGELOG entries for this version
402+ CHANGELOG_ENTRIES=$(python3 -c "
403+ import re, os
404+ version = os.environ['VERSION']
405+ with open('CHANGELOG.md', 'r') as f:
406+ content = f.read()
407+ version_pattern = rf'## v{re.escape(version)}.*?\n(.*?)(?=\n## |\Z)'
408+ version_match = re.search(version_pattern, content, re.DOTALL)
409+ if version_match:
410+ entries = version_match.group(1).strip()
411+ if entries:
412+ print(entries)
413+ ")
414+
415+ # Create release notes
416+ cat > release_notes.md << EOF
417+ $(if [ -n "$CHANGELOG_ENTRIES" ]; then echo "## What's Changed"; echo "$CHANGELOG_ENTRIES"; echo ""; fi)
418+
419+ ## Upstream Components
420+
421+ $DEPS
422+
423+ ## Release Artifacts
424+
425+ This release publishes to public ECR and PyPi.
426+ * See ADOT Python auto-instrumentation Docker image v$VERSION in our public ECR repository:
427+ https://gallery.ecr.aws/aws-observability/adot-autoinstrumentation-python
428+ * See version $VERSION in our PyPi repository:
429+ https://pypi.org/project/aws-opentelemetry-distro/
430+
431+ ## Lambda Layer
432+
433+ This release includes the AWS OpenTelemetry Lambda Layer for Python version $VERSION-$(echo $GITHUB_SHA | cut -c1-7).
434+
435+ Lambda Layer ARNs:
436+ ${{ needs.generate-lambda-release-note.outputs.layer-note }}
437+ EOF
438+
439+ shasum -a 256 ${{ env.ARTIFACT_NAME }} > ${{ env.ARTIFACT_NAME }}.sha256
440+ shasum -a 256 layer.zip > layer.zip.sha256
158441
159442 gh release create --target "$GITHUB_REF_NAME" \
160- --title "Release v${{ github.event.inputs.version }}" \
443+ --title "Release v$VERSION" \
444+ --notes-file release_notes.md \
161445 --draft \
162- "v${{ github.event.inputs.version }} " \
163- dist/ ${{ env.ARTIFACT_NAME }} \
446+ "v$VERSION " \
447+ ${{ env.ARTIFACT_NAME }} \
164448 ${{ env.ARTIFACT_NAME }}.sha256 \
165- layer_artifact/ layer.zip \
166- layer_artifact/ layer.zip.sha256
449+ layer.zip \
450+ layer.zip.sha256
0 commit comments