Skip to content

Commit e45a245

Browse files
XinRanZhAWSsrprashdependabot[bot]Jeel-mehtaJeel Mehta
authored
Preparing release for version 2.0.1 (#1045)
*Description of changes:* Release preparation for version 2.0.1 *Dependency* ------------------------------------------------------------ :dependencyManagement Project Dependency Updates (report to plain text file) ------------------------------------------------------------ The following dependencies are using the latest release version: - com.sparkjava:spark-core:2.9.4 - com.squareup.okhttp3:okhttp:4.12.0 - io.opentelemetry:opentelemetry-extension-aws:1.20.1 The following dependencies have later release versions: - com.amazonaws:aws-java-sdk-bom [1.12.599 -> 1.12.782] https://aws.amazon.com/sdkforjava - com.fasterxml.jackson:jackson-bom [2.16.0 -> 2.18.3] https://github.com/FasterXML/jackson-bom - com.github.ben-manes.versions:com.github.ben-manes.versions.gradle.plugin [0.50.0 -> 0.52.0] - com.google.guava:guava-bom [33.0.0-jre -> 33.4.0-jre] https://github.com/google/guava - com.google.protobuf:protobuf-bom [3.25.1 -> 4.30.0] https://developers.google.com/protocol-buffers/ - com.linecorp.armeria:armeria-bom [1.26.4 -> 1.32.0] https://armeria.dev/ - commons-logging:commons-logging [1.2 -> 1.3.5] https://commons.apache.org/proper/commons-logging/ - io.grpc:grpc-bom [1.59.1 -> 1.71.0] https://github.com/grpc/grpc-java - io.opentelemetry.contrib:opentelemetry-aws-resources [1.39.0-alpha -> 1.44.0-alpha] https://github.com/open-telemetry/opentelemetry-java-contrib - io.opentelemetry.contrib:opentelemetry-aws-xray [1.39.0 -> 1.44.0] https://github.com/open-telemetry/opentelemetry-java-contrib - io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha [2.10.0-adot2-alpha -> 2.13.3-alpha] https://github.com/open-telemetry/opentelemetry-java-instrumentation - io.opentelemetry.javaagent:opentelemetry-javaagent [2.10.0-adot2 -> 2.13.3] https://github.com/open-telemetry/opentelemetry-java-instrumentation - io.opentelemetry.proto:opentelemetry-proto [1.0.0-alpha -> 1.5.0-alpha] https://github.com/open-telemetry/opentelemetry-proto-java - net.bytebuddy:byte-buddy [1.14.10 -> 1.17.2] https://bytebuddy.net - org.apache.logging.log4j:log4j-bom [2.21.1 -> 2.24.3] https://logging.apache.org/log4j/2.x/ - org.assertj:assertj-core [3.24.2 -> 3.27.3] https://assertj.github.io/doc/#assertj-core - org.curioswitch.curiostack:protobuf-jackson [2.2.0 -> 2.7.0] https://github.com/curioswitch/protobuf-jackson - org.junit:junit-bom [5.10.1 -> 5.12.0] https://junit.org/junit5/ - org.slf4j:slf4j-api [1.7.36 -> 2.0.17] http://www.slf4j.org - org.slf4j:slf4j-simple [1.7.36 -> 2.0.17] http://www.slf4j.org - org.springframework.boot:spring-boot-dependencies [2.7.17 -> 3.4.3] https://spring.io/projects/spring-boot - org.testcontainers:testcontainers-bom [1.19.3 -> 1.20.6] https://java.testcontainers.org - software.amazon.awssdk:bom [2.21.33 -> 2.30.37] https://aws.amazon.com/sdkforjava Gradle release-candidate updates: - Gradle: [8.10 -> 8.13] By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. --------- Signed-off-by: dependabot[bot] <[email protected]> Co-authored-by: Prashant Srivastava <[email protected]> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jeel-mehta <[email protected]> Co-authored-by: Jeel Mehta <[email protected]> Co-authored-by: Harry <[email protected]> Co-authored-by: Steve Liu <[email protected]> Co-authored-by: Mahad Janjua <[email protected]> Co-authored-by: Lei Wang <[email protected]> Co-authored-by: Mengyi Zhou (bjrara) <[email protected]> Co-authored-by: Michael He <[email protected]>
1 parent e3ea5ab commit e45a245

File tree

18 files changed

+395
-54
lines changed

18 files changed

+395
-54
lines changed

.github/patches/opentelemetry-java-instrumentation.patch

+3-3
Original file line numberDiff line numberDiff line change
@@ -3522,14 +3522,14 @@ index 2533a0202d..a275e7e2f7 100644
35223522
// spans because of https://github.com/aws/aws-sdk-java-v2/issues/1741. We should at least tweak
35233523
// the instrumentation to add Events for retries instead.
35243524
diff --git a/version.gradle.kts b/version.gradle.kts
3525-
index 7900c9a4d9..57b4d36c0a 100644
3525+
index 7900c9a4d9..0dc0460cbc 100644
35263526
--- a/version.gradle.kts
35273527
+++ b/version.gradle.kts
35283528
@@ -1,5 +1,5 @@
35293529
-val stableVersion = "2.10.0"
35303530
-val alphaVersion = "2.10.0-alpha"
3531-
+val stableVersion = "2.10.0-adot1"
3532-
+val alphaVersion = "2.10.0-adot1-alpha"
3531+
+val stableVersion = "2.10.0-adot2"
3532+
+val alphaVersion = "2.10.0-adot2-alpha"
35333533

35343534
allprojects {
35353535
if (findProperty("otel.stable") != "true") {

.github/workflows/application-signals-e2e-test.yml

+13
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,19 @@ jobs:
205205
java-version: '11'
206206
cpu-architecture: 'arm64'
207207

208+
#
209+
# UBUNTU COVERAGE
210+
# DEFAULT SETTING: Java 11, EC2, AMD64, Ubuntu
211+
#
212+
213+
v11-amd64-ubuntu:
214+
needs: [ upload-main-build ]
215+
uses: aws-observability/aws-application-signals-test-framework/.github/workflows/java-ec2-ubuntu-test.yml@main
216+
secrets: inherit
217+
with:
218+
aws-region: us-east-1
219+
caller-workflow-name: 'main-build'
220+
208221
#
209222
# Other Functional Test Case
210223
#

.github/workflows/owasp.yml

+45-11
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,9 @@ jobs:
6161
if: always()
6262
run: |
6363
gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 259A55407DD6C00299E6607EFFDE55BE73A2D1ED
64-
VERSION=$(curl -s https://jeremylong.github.io/DependencyCheck/current.txt)
65-
curl -Ls "https://github.com/jeremylong/DependencyCheck/releases/download/v$VERSION/dependency-check-$VERSION-release.zip" --output dependency-check.zip
66-
curl -Ls "https://github.com/jeremylong/DependencyCheck/releases/download/v$VERSION/dependency-check-$VERSION-release.zip.asc" --output dependency-check.zip.asc
64+
VERSION=$(curl -s https://jeremylong.github.io/DependencyCheck/current.txt | head -n1 | cut -d' ' -f1)
65+
curl -Ls "https://github.com/dependency-check/DependencyCheck/releases/download/v$VERSION/dependency-check-$VERSION-release.zip" --output dependency-check.zip
66+
curl -Ls "https://github.com/dependency-check/DependencyCheck/releases/download/v$VERSION/dependency-check-$VERSION-release.zip.asc" --output dependency-check.zip.asc
6767
gpg --verify dependency-check.zip.asc
6868
unzip dependency-check.zip
6969
./dependency-check/bin/dependency-check.sh --failOnCVSS 0 --nvdApiKey ${{ env.NVD_API_KEY_NVD_API_KEY }} -s 'otelagent/build/libs/aws-opentelemetry-agent-*-SNAPSHOT.jar'
@@ -72,17 +72,33 @@ jobs:
7272
if: ${{ steps.dep_scan.outcome != 'success' }}
7373
run: less dependency-check-report.html
7474

75-
- name: Perform high image scan
75+
- name: Perform high image scan on v1
7676
if: always()
77-
id: high_scan
77+
id: high_scan_v1
7878
uses: ./.github/actions/image_scan
7979
with:
8080
image-ref: "public.ecr.aws/aws-observability/adot-autoinstrumentation-java:v2.0.0"
8181
severity: 'CRITICAL,HIGH'
8282

83-
- name: Perform low image scan
83+
- name: Perform low image scan on v1
8484
if: always()
85-
id: low_scan
85+
id: low_scan_v1
86+
uses: ./.github/actions/image_scan
87+
with:
88+
image-ref: "public.ecr.aws/aws-observability/adot-autoinstrumentation-java:v2.0.0"
89+
severity: 'MEDIUM,LOW,UNKNOWN'
90+
91+
- name: Perform high image scan on v2
92+
if: always()
93+
id: high_scan_v2
94+
uses: ./.github/actions/image_scan
95+
with:
96+
image-ref: "public.ecr.aws/aws-observability/adot-autoinstrumentation-java:v2.0.0"
97+
severity: 'CRITICAL,HIGH'
98+
99+
- name: Perform low image scan on v2
100+
if: always()
101+
id: low_scan_v2
86102
uses: ./.github/actions/image_scan
87103
with:
88104
image-ref: "public.ecr.aws/aws-observability/adot-autoinstrumentation-java:v2.0.0"
@@ -95,19 +111,37 @@ jobs:
95111
role-to-assume: ${{ secrets.METRICS_ROLE_ARN }}
96112
aws-region: ${{ env.AWS_DEFAULT_REGION }}
97113

98-
- name: Publish high scan status
114+
- name: Publish high scan status on v1
99115
if: always()
100116
run: |
101-
value="${{ steps.high_scan.outcome == 'success' && '1.0' || '0.0' }}"
117+
value="${{ steps.high_scan_v1.outcome == 'success' && '1.0' || '0.0' }}"
102118
aws cloudwatch put-metric-data --namespace 'ADOT/GitHubActions' \
103119
--metric-name Success \
104120
--dimensions repository=${{ github.repository }},branch=${{ github.ref_name }},workflow=daily_scan_high \
105121
--value $value
106122
107-
- name: Publish low scan status
123+
- name: Publish high scan status on v2
124+
if: always()
125+
run: |
126+
value="${{ steps.high_scan_v2.outcome == 'success' && '1.0' || '0.0' }}"
127+
aws cloudwatch put-metric-data --namespace 'ADOT/GitHubActions' \
128+
--metric-name Success \
129+
--dimensions repository=${{ github.repository }},branch=${{ github.ref_name }},workflow=daily_scan_high \
130+
--value $value
131+
132+
- name: Publish low scan status on v1
133+
if: always()
134+
run: |
135+
value="${{ steps.low_scan_v1.outcome == 'success' && steps.dep_scan.outcome == 'success' && '1.0' || '0.0'}}"
136+
aws cloudwatch put-metric-data --namespace 'ADOT/GitHubActions' \
137+
--metric-name Success \
138+
--dimensions repository=${{ github.repository }},branch=${{ github.ref_name }},workflow=daily_scan_low \
139+
--value $value
140+
141+
- name: Publish low scan status on v2
108142
if: always()
109143
run: |
110-
value="${{ steps.low_scan.outcome == 'success' && steps.dep_scan.outcome == 'success' && '1.0' || '0.0'}}"
144+
value="${{ steps.low_scan_v2.outcome == 'success' && steps.dep_scan.outcome == 'success' && '1.0' || '0.0'}}"
111145
aws cloudwatch put-metric-data --namespace 'ADOT/GitHubActions' \
112146
--metric-name Success \
113147
--dimensions repository=${{ github.repository }},branch=${{ github.ref_name }},workflow=daily_scan_low \

.github/workflows/release-build.yml

+9-1
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,17 @@ jobs:
129129
env:
130130
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
131131
run: |
132+
# Download layer.zip from existing latest tagged SDK release note
133+
LATEST_SDK_VERSION=$(gh release list --repo "aws-observability/aws-otel-java-instrumentation" --json tagName,isLatest -q 'map(select(.isLatest==true)) | .[0].tagName')
134+
mkdir -p layer_artifact
135+
gh release download "$LATEST_SDK_VERSION" --repo "aws-observability/aws-otel-java-instrumentation" --pattern "layer.zip" --dir layer_artifact
136+
shasum -a 256 layer_artifact/layer.zip > layer_artifact/layer.zip.sha256
137+
132138
gh release create --target "$GITHUB_REF_NAME" \
133139
--title "Release v${{ github.event.inputs.version }}" \
134140
--draft \
135141
"v${{ github.event.inputs.version }}" \
136142
${{ env.ARTIFACT_NAME }} \
137-
${{ env.ARTIFACT_NAME }}.sha256
143+
${{ env.ARTIFACT_NAME }}.sha256 \
144+
layer_artifact/layer.zip \
145+
layer_artifact/layer.zip.sha256

.github/workflows/release-lambda.yml

+236
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
name: Release Java Lambda layer
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version:
7+
description: The version to tag the lambda release with, e.g., 1.2.0
8+
required: true
9+
aws_region:
10+
description: 'Deploy to aws regions'
11+
required: true
12+
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'
13+
14+
env:
15+
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
16+
LAYER_NAME: AWSOpenTelemetryDistroJava
17+
18+
permissions:
19+
id-token: write
20+
contents: write
21+
22+
jobs:
23+
build-layer:
24+
runs-on: ubuntu-latest
25+
outputs:
26+
aws_regions_json: ${{ steps.set-matrix.outputs.aws_regions_json }}
27+
steps:
28+
- name: Set up regions matrix
29+
id: set-matrix
30+
run: |
31+
IFS=',' read -ra REGIONS <<< "${{ github.event.inputs.aws_region }}"
32+
MATRIX="["
33+
for region in "${REGIONS[@]}"; do
34+
trimmed_region=$(echo "$region" | xargs)
35+
MATRIX+="\"$trimmed_region\","
36+
done
37+
MATRIX="${MATRIX%,}]"
38+
echo ${MATRIX}
39+
echo "aws_regions_json=${MATRIX}" >> $GITHUB_OUTPUT
40+
41+
- name: Checkout Repo @ SHA - ${{ github.sha }}
42+
uses: actions/checkout@v4
43+
44+
- uses: actions/setup-java@v4
45+
with:
46+
java-version: 17
47+
distribution: 'temurin'
48+
49+
- name: Build layers
50+
working-directory: lambda-layer
51+
run: |
52+
./build-layer.sh
53+
54+
- name: Upload layer
55+
uses: actions/upload-artifact@v4
56+
with:
57+
name: aws-opentelemetry-java-layer.zip
58+
path: lambda-layer/build/distributions/aws-opentelemetry-java-layer.zip
59+
60+
publish-prod:
61+
runs-on: ubuntu-latest
62+
needs: build-layer
63+
strategy:
64+
matrix:
65+
aws_region: ${{ fromJson(needs.build-layer.outputs.aws_regions_json) }}
66+
steps:
67+
- name: role arn
68+
env:
69+
COMMERCIAL_REGIONS: ${{ env.COMMERCIAL_REGIONS }}
70+
run: |
71+
COMMERCIAL_REGIONS_ARRAY=(${COMMERCIAL_REGIONS//,/ })
72+
FOUND=false
73+
for REGION in "${COMMERCIAL_REGIONS_ARRAY[@]}"; do
74+
if [[ "$REGION" == "${{ matrix.aws_region }}" ]]; then
75+
FOUND=true
76+
break
77+
fi
78+
done
79+
if [ "$FOUND" = true ]; then
80+
echo "Found ${{ matrix.aws_region }} in COMMERCIAL_REGIONS"
81+
SECRET_KEY="LAMBDA_LAYER_RELEASE"
82+
else
83+
echo "Not found ${{ matrix.aws_region }} in COMMERCIAL_REGIONS"
84+
SECRET_KEY="${{ matrix.aws_region }}_LAMBDA_LAYER_RELEASE"
85+
fi
86+
SECRET_KEY=${SECRET_KEY//-/_}
87+
echo "SECRET_KEY=${SECRET_KEY}" >> $GITHUB_ENV
88+
89+
- uses: aws-actions/[email protected]
90+
with:
91+
role-to-assume: ${{ secrets[env.SECRET_KEY] }}
92+
role-duration-seconds: 1200
93+
aws-region: ${{ matrix.aws_region }}
94+
95+
- name: Get s3 bucket name for release
96+
run: |
97+
echo BUCKET_NAME=java-lambda-layer-${{ github.run_id }}-${{ matrix.aws_region }} | tee --append $GITHUB_ENV
98+
99+
- name: download layer.zip
100+
uses: actions/download-artifact@v4
101+
with:
102+
name: aws-opentelemetry-java-layer.zip
103+
104+
- name: publish
105+
run: |
106+
aws s3 mb s3://${{ env.BUCKET_NAME }}
107+
aws s3 cp aws-opentelemetry-java-layer.zip s3://${{ env.BUCKET_NAME }}
108+
layerARN=$(
109+
aws lambda publish-layer-version \
110+
--layer-name ${{ env.LAYER_NAME }} \
111+
--content S3Bucket=${{ env.BUCKET_NAME }},S3Key=aws-opentelemetry-java-layer.zip \
112+
--compatible-runtimes java17 java21 \
113+
--compatible-architectures "arm64" "x86_64" \
114+
--license-info "Apache-2.0" \
115+
--description "AWS Distro of OpenTelemetry Lambda Layer for Java Runtime" \
116+
--query 'LayerVersionArn' \
117+
--output text
118+
)
119+
echo $layerARN
120+
echo "LAYER_ARN=${layerARN}" >> $GITHUB_ENV
121+
mkdir ${{ env.LAYER_NAME }}
122+
echo $layerARN > ${{ env.LAYER_NAME }}/${{ matrix.aws_region }}
123+
cat ${{ env.LAYER_NAME }}/${{ matrix.aws_region }}
124+
125+
- name: public layer
126+
run: |
127+
layerVersion=$(
128+
aws lambda list-layer-versions \
129+
--layer-name ${{ env.LAYER_NAME }} \
130+
--query 'max_by(LayerVersions, &Version).Version'
131+
)
132+
aws lambda add-layer-version-permission \
133+
--layer-name ${{ env.LAYER_NAME }} \
134+
--version-number $layerVersion \
135+
--principal "*" \
136+
--statement-id publish \
137+
--action lambda:GetLayerVersion
138+
139+
- name: upload layer arn artifact
140+
if: ${{ success() }}
141+
uses: actions/upload-artifact@v4
142+
with:
143+
name: ${{ env.LAYER_NAME }}
144+
path: ${{ env.LAYER_NAME }}/${{ matrix.aws_region }}
145+
146+
- name: clean s3
147+
if: always()
148+
run: |
149+
aws s3 rb --force s3://${{ env.BUCKET_NAME }}
150+
151+
generate-release-note:
152+
runs-on: ubuntu-latest
153+
needs: publish-prod
154+
steps:
155+
- name: Checkout Repo @ SHA - ${{ github.sha }}
156+
uses: actions/checkout@v4
157+
- uses: hashicorp/setup-terraform@v2
158+
- name: download layerARNs
159+
uses: actions/download-artifact@v4
160+
with:
161+
pattern: ${{ env.LAYER_NAME }}-*
162+
path: ${{ env.LAYER_NAME }}
163+
merge-multiple: true
164+
- name: show layerARNs
165+
run: |
166+
for file in ${{ env.LAYER_NAME }}/*
167+
do
168+
echo $file
169+
cat $file
170+
done
171+
- name: generate layer-note
172+
working-directory: ${{ env.LAYER_NAME }}
173+
run: |
174+
echo "| Region | Layer ARN |" >> ../layer-note
175+
echo "| ---- | ---- |" >> ../layer-note
176+
for file in *
177+
do
178+
read arn < $file
179+
echo "| " $file " | " $arn " |" >> ../layer-note
180+
done
181+
cat ../layer-note
182+
- name: generate tf layer
183+
working-directory: ${{ env.LAYER_NAME }}
184+
run: |
185+
echo "locals {" >> ../layer_arns.tf
186+
echo " sdk_layer_arns = {" >> ../layer_arns.tf
187+
for file in *
188+
do
189+
read arn < $file
190+
echo " \""$file"\" = \""$arn"\"" >> ../layer_arns.tf
191+
done
192+
cd ..
193+
echo " }" >> layer_arns.tf
194+
echo "}" >> layer_arns.tf
195+
terraform fmt layer_arns.tf
196+
cat layer_arns.tf
197+
- name: download layer.zip
198+
uses: actions/download-artifact@v4
199+
with:
200+
name: layer.zip
201+
- name: Get commit hash
202+
id: commit
203+
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
204+
- name: Create Release Notes
205+
run: |
206+
echo "AWS OpenTelemetry Lambda Layer for Java version ${{ github.event.inputs.version }}-${{ steps.commit.outputs.sha_short }}" > release_notes.md
207+
echo "" >> release_notes.md
208+
echo "" >> release_notes.md
209+
echo "See new Lambda Layer ARNs:" >> release_notes.md
210+
echo "" >> release_notes.md
211+
cat layer-note >> release_notes.md
212+
echo "" >> release_notes.md
213+
echo "Notes:" >> release_notes.md
214+
- name: Create GH release
215+
id: create_release
216+
env:
217+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
218+
run: |
219+
gh release create --target "$GITHUB_REF_NAME" \
220+
--title "Release lambda-v${{ github.event.inputs.version }}-${{ steps.commit.outputs.sha_short }}" \
221+
--notes-file release_notes.md \
222+
--draft \
223+
"lambda-v${{ github.event.inputs.version }}-${{ steps.commit.outputs.sha_short }}" \
224+
layer_arns.tf layer.zip
225+
echo Removing release_notes.md ...
226+
rm -f release_notes.md
227+
- name: Upload layer.zip and SHA-256 checksum to SDK Release Notes (tagged with latest)
228+
env:
229+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
230+
run: |
231+
LATEST_SDK_VERSION=$(gh release list --repo "aws-observability/aws-otel-java-instrumentation" --json tagName,isLatest -q 'map(select(.isLatest==true)) | .[0].tagName')
232+
# Generate SHA-256 checksum for layer.zip
233+
shasum -a 256 layer.zip > layer.zip.sha256
234+
# Upload layer.zip and its checksum to the latest SDK release note
235+
gh release upload "$LATEST_SDK_VERSION" layer.zip layer.zip.sha256 --repo "aws-observability/aws-otel-java-instrumentation" --clobber
236+
echo "✅ layer.zip successfully uploaded to $LATEST_SDK_VERSION in the upstream repo!"

appsignals-tests/images/grpc/grpc-base/build.gradle.kts

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ protobuf {
3636
}
3737
plugins {
3838
create("grpc") {
39-
artifact = "io.grpc:protoc-gen-grpc-java:1.56.1"
39+
artifact = "io.grpc:protoc-gen-grpc-java:1.69.1"
4040
}
4141
}
4242
generateProtoTasks {

0 commit comments

Comments
 (0)