Skip to content

Commit 615bf86

Browse files
authored
Add buildspec for tests (#4401)
1 parent bcc1ab6 commit 615bf86

File tree

9 files changed

+511
-0
lines changed

9 files changed

+511
-0
lines changed

buildspec/linuxTestsForAmazonQ.yml

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
version: 0.2
2+
3+
cache:
4+
paths:
5+
# - '/root/.gradle/caches/**/*'
6+
- '/root/.gradle/wrapper/**/*'
7+
8+
env:
9+
variables:
10+
CI: true
11+
LOCAL_ENV_RUN: true
12+
13+
phases:
14+
install:
15+
commands:
16+
- useradd codebuild-user
17+
- dnf install -y acl
18+
- chown -R codebuild-user:codebuild-user /codebuild/output
19+
- chown -R codebuild-user:codebuild-user /codebuild/local-cache
20+
- setfacl -m d:o::rwx,o::rwx /root
21+
# (CVE-2022-24765) fatal: detected dubious ownership in repository
22+
- su codebuild-user -c "git config --global --add safe.directory \"$CODEBUILD_SRC_DIR\""
23+
24+
build:
25+
commands:
26+
- |
27+
if [ "$CODEARTIFACT_DOMAIN_NAME" ] && [ "$CODEARTIFACT_REPO_NAME" ]; then
28+
CODEARTIFACT_URL=$(aws codeartifact get-repository-endpoint --domain $CODEARTIFACT_DOMAIN_NAME --repository $CODEARTIFACT_REPO_NAME --format maven --query repositoryEndpoint --output text)
29+
CODEARTIFACT_NUGET_URL=$(aws codeartifact get-repository-endpoint --domain $CODEARTIFACT_DOMAIN_NAME --repository $CODEARTIFACT_REPO_NAME --format nuget --query repositoryEndpoint --output text)
30+
CODEARTIFACT_AUTH_TOKEN=$(aws codeartifact get-authorization-token --domain $CODEARTIFACT_DOMAIN_NAME --query authorizationToken --output text --duration-seconds 3600)
31+
su codebuild-user -c "dotnet codeartifact-creds install"
32+
fi
33+
34+
- chmod +x gradlew
35+
- su codebuild-user -c "./gradlew -PideProfileName=$ALTERNATIVE_IDE_PROFILE_NAME :plugin-amazonq:check coverageReport --info --console plain --continue"
36+
- ./gradlew -PideProfileName=$ALTERNATIVE_IDE_PROFILE_NAME :plugin-amazonq:buildPlugin
37+
- VCS_COMMIT_ID="${CODEBUILD_RESOLVED_SOURCE_VERSION}"
38+
- CI_BUILD_URL=$(echo $CODEBUILD_BUILD_URL | sed 's/#/%23/g') # Encode `#` in the URL because otherwise the url is clipped in the Codecov.io site
39+
- CI_BUILD_ID="${CODEBUILD_BUILD_ID}"
40+
- test -n "$CODE_COV_TOKEN" && curl -Os https://uploader.codecov.io/latest/linux/codecov && chmod +x codecov || true # this sometimes times out but we don't want to fail the build
41+
- test -n "$CODE_COV_TOKEN" && test -n "$CODEBUILD_BUILD_SUCCEEDING" && ./codecov -t $CODE_COV_TOKEN -F unittest || true
42+
- test -n "$CODE_COV_TOKEN" && test -n "$CODEBUILD_BUILD_SUCCEEDING" && ./codecov -t $CODE_COV_TOKEN -F codewhisperer || true
43+
44+
post_build:
45+
commands:
46+
- BUILD_ARTIFACTS="/tmp/buildArtifacts"
47+
- TEST_ARTIFACTS="/tmp/testArtifacts"
48+
- mkdir -p $TEST_ARTIFACTS/test-reports
49+
- mkdir -p $BUILD_ARTIFACTS
50+
- rsync -rmq --include='*/' --include '**/build/idea-sandbox/system*/log/**' --exclude='*' . $TEST_ARTIFACTS/ || true
51+
- rsync -rmq --include='*/' --include '**/build/reports/**' --exclude='*' . $TEST_ARTIFACTS/ || true
52+
- rsync -rmq --include='*/' --include '**/test-results/**/*.xml' --exclude='*' . $TEST_ARTIFACTS/test-reports || true
53+
- cp -r ./plugins/core/build/distributions/*.zip $BUILD_ARTIFACTS/ || touch $BUILD_ARTIFACTS/build_failed
54+
55+
reports:
56+
unit-test:
57+
files:
58+
- "**/*"
59+
base-directory: /tmp/testArtifacts/test-reports
60+
discard-paths: yes
61+
62+
artifacts:
63+
files:
64+
- "**/*"
65+
base-directory: /tmp/testArtifacts
66+
secondary-artifacts:
67+
plugin:
68+
files:
69+
- /tmp/buildArtifacts/*
70+
discard-paths: yes
71+
name: plugin.zip

buildspec/linuxTestsForCore.yml

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
version: 0.2
2+
3+
cache:
4+
paths:
5+
# - '/root/.gradle/caches/**/*'
6+
- '/root/.gradle/wrapper/**/*'
7+
8+
env:
9+
variables:
10+
CI: true
11+
LOCAL_ENV_RUN: true
12+
13+
phases:
14+
install:
15+
commands:
16+
- useradd codebuild-user
17+
- dnf install -y acl
18+
- chown -R codebuild-user:codebuild-user /codebuild/output
19+
- chown -R codebuild-user:codebuild-user /codebuild/local-cache
20+
- setfacl -m d:o::rwx,o::rwx /root
21+
# (CVE-2022-24765) fatal: detected dubious ownership in repository
22+
- su codebuild-user -c "git config --global --add safe.directory \"$CODEBUILD_SRC_DIR\""
23+
24+
build:
25+
commands:
26+
- |
27+
if [ "$CODEARTIFACT_DOMAIN_NAME" ] && [ "$CODEARTIFACT_REPO_NAME" ]; then
28+
CODEARTIFACT_URL=$(aws codeartifact get-repository-endpoint --domain $CODEARTIFACT_DOMAIN_NAME --repository $CODEARTIFACT_REPO_NAME --format maven --query repositoryEndpoint --output text)
29+
CODEARTIFACT_NUGET_URL=$(aws codeartifact get-repository-endpoint --domain $CODEARTIFACT_DOMAIN_NAME --repository $CODEARTIFACT_REPO_NAME --format nuget --query repositoryEndpoint --output text)
30+
CODEARTIFACT_AUTH_TOKEN=$(aws codeartifact get-authorization-token --domain $CODEARTIFACT_DOMAIN_NAME --query authorizationToken --output text --duration-seconds 3600)
31+
su codebuild-user -c "dotnet codeartifact-creds install"
32+
fi
33+
34+
- chmod +x gradlew
35+
- su codebuild-user -c "./gradlew -PideProfileName=$ALTERNATIVE_IDE_PROFILE_NAME :plugin-core:check coverageReport --info --console plain --continue"
36+
- ./gradlew -PideProfileName=$ALTERNATIVE_IDE_PROFILE_NAME :plugin-core:buildPlugin
37+
- VCS_COMMIT_ID="${CODEBUILD_RESOLVED_SOURCE_VERSION}"
38+
- CI_BUILD_URL=$(echo $CODEBUILD_BUILD_URL | sed 's/#/%23/g') # Encode `#` in the URL because otherwise the url is clipped in the Codecov.io site
39+
- CI_BUILD_ID="${CODEBUILD_BUILD_ID}"
40+
- test -n "$CODE_COV_TOKEN" && curl -Os https://uploader.codecov.io/latest/linux/codecov && chmod +x codecov || true # this sometimes times out but we don't want to fail the build
41+
- test -n "$CODE_COV_TOKEN" && test -n "$CODEBUILD_BUILD_SUCCEEDING" && ./codecov -t $CODE_COV_TOKEN -F unittest || true
42+
- test -n "$CODE_COV_TOKEN" && test -n "$CODEBUILD_BUILD_SUCCEEDING" && ./codecov -t $CODE_COV_TOKEN -F codewhisperer || true
43+
44+
post_build:
45+
commands:
46+
- BUILD_ARTIFACTS="/tmp/buildArtifacts"
47+
- TEST_ARTIFACTS="/tmp/testArtifacts"
48+
- mkdir -p $TEST_ARTIFACTS/test-reports
49+
- mkdir -p $BUILD_ARTIFACTS
50+
- rsync -rmq --include='*/' --include '**/build/idea-sandbox/system*/log/**' --exclude='*' . $TEST_ARTIFACTS/ || true
51+
- rsync -rmq --include='*/' --include '**/build/reports/**' --exclude='*' . $TEST_ARTIFACTS/ || true
52+
- rsync -rmq --include='*/' --include '**/test-results/**/*.xml' --exclude='*' . $TEST_ARTIFACTS/test-reports || true
53+
- cp -r ./plugins/core/build/distributions/*.zip $BUILD_ARTIFACTS/ || touch $BUILD_ARTIFACTS/build_failed
54+
55+
reports:
56+
unit-test:
57+
files:
58+
- "**/*"
59+
base-directory: /tmp/testArtifacts/test-reports
60+
discard-paths: yes
61+
62+
artifacts:
63+
files:
64+
- "**/*"
65+
base-directory: /tmp/testArtifacts
66+
secondary-artifacts:
67+
plugin:
68+
files:
69+
- /tmp/buildArtifacts/*
70+
discard-paths: yes
71+
name: plugin.zip

buildspec/linuxTestsForToolkit.yml

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
version: 0.2
2+
3+
cache:
4+
paths:
5+
# - '/root/.gradle/caches/**/*'
6+
- '/root/.gradle/wrapper/**/*'
7+
8+
env:
9+
variables:
10+
CI: true
11+
LOCAL_ENV_RUN: true
12+
13+
phases:
14+
install:
15+
commands:
16+
- useradd codebuild-user
17+
- dnf install -y acl
18+
- chown -R codebuild-user:codebuild-user /codebuild/output
19+
- chown -R codebuild-user:codebuild-user /codebuild/local-cache
20+
- setfacl -m d:o::rwx,o::rwx /root
21+
# (CVE-2022-24765) fatal: detected dubious ownership in repository
22+
- su codebuild-user -c "git config --global --add safe.directory \"$CODEBUILD_SRC_DIR\""
23+
24+
build:
25+
commands:
26+
- |
27+
if [ "$CODEARTIFACT_DOMAIN_NAME" ] && [ "$CODEARTIFACT_REPO_NAME" ]; then
28+
CODEARTIFACT_URL=$(aws codeartifact get-repository-endpoint --domain $CODEARTIFACT_DOMAIN_NAME --repository $CODEARTIFACT_REPO_NAME --format maven --query repositoryEndpoint --output text)
29+
CODEARTIFACT_NUGET_URL=$(aws codeartifact get-repository-endpoint --domain $CODEARTIFACT_DOMAIN_NAME --repository $CODEARTIFACT_REPO_NAME --format nuget --query repositoryEndpoint --output text)
30+
CODEARTIFACT_AUTH_TOKEN=$(aws codeartifact get-authorization-token --domain $CODEARTIFACT_DOMAIN_NAME --query authorizationToken --output text --duration-seconds 3600)
31+
su codebuild-user -c "dotnet codeartifact-creds install"
32+
fi
33+
34+
- chmod +x gradlew
35+
- su codebuild-user -c "./gradlew -PideProfileName=$ALTERNATIVE_IDE_PROFILE_NAME :plugin-toolkit:intellij-standalone:check coverageReport --info --console plain --continue"
36+
- ./gradlew -PideProfileName=$ALTERNATIVE_IDE_PROFILE_NAME :plugin-toolkit:intellij-standalone:buildPlugin
37+
- VCS_COMMIT_ID="${CODEBUILD_RESOLVED_SOURCE_VERSION}"
38+
- CI_BUILD_URL=$(echo $CODEBUILD_BUILD_URL | sed 's/#/%23/g') # Encode `#` in the URL because otherwise the url is clipped in the Codecov.io site
39+
- CI_BUILD_ID="${CODEBUILD_BUILD_ID}"
40+
- test -n "$CODE_COV_TOKEN" && curl -Os https://uploader.codecov.io/latest/linux/codecov && chmod +x codecov || true # this sometimes times out but we don't want to fail the build
41+
- test -n "$CODE_COV_TOKEN" && test -n "$CODEBUILD_BUILD_SUCCEEDING" && ./codecov -t $CODE_COV_TOKEN -F unittest || true
42+
- test -n "$CODE_COV_TOKEN" && test -n "$CODEBUILD_BUILD_SUCCEEDING" && ./codecov -t $CODE_COV_TOKEN -F codewhisperer || true
43+
44+
post_build:
45+
commands:
46+
- BUILD_ARTIFACTS="/tmp/buildArtifacts"
47+
- TEST_ARTIFACTS="/tmp/testArtifacts"
48+
- mkdir -p $TEST_ARTIFACTS/test-reports
49+
- mkdir -p $BUILD_ARTIFACTS
50+
- rsync -rmq --include='*/' --include '**/build/idea-sandbox/system*/log/**' --exclude='*' . $TEST_ARTIFACTS/ || true
51+
- rsync -rmq --include='*/' --include '**/build/reports/**' --exclude='*' . $TEST_ARTIFACTS/ || true
52+
- rsync -rmq --include='*/' --include '**/test-results/**/*.xml' --exclude='*' . $TEST_ARTIFACTS/test-reports || true
53+
- cp -r ./plugins/toolkit/intellij-standalone/build/distributions/*.zip $BUILD_ARTIFACTS/ || touch $BUILD_ARTIFACTS/build_failed
54+
55+
reports:
56+
unit-test:
57+
files:
58+
- "**/*"
59+
base-directory: /tmp/testArtifacts/test-reports
60+
discard-paths: yes
61+
62+
artifacts:
63+
files:
64+
- "**/*"
65+
base-directory: /tmp/testArtifacts
66+
secondary-artifacts:
67+
plugin:
68+
files:
69+
- /tmp/buildArtifacts/*
70+
discard-paths: yes
71+
name: plugin.zip
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
version: 0.2
2+
3+
env:
4+
variables:
5+
CI: true
6+
LOCAL_ENV_RUN: true
7+
8+
phases:
9+
install:
10+
runtime-versions:
11+
java: corretto17
12+
13+
commands:
14+
- |
15+
if(-Not($Env:CODE_COV_TOKEN -eq $null)) {
16+
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;
17+
Invoke-WebRequest -Uri https://uploader.codecov.io/latest/windows/codecov.exe -Outfile codecov.exe
18+
}
19+
- dotnet --list-sdks
20+
- |
21+
$DOTNET_ROOT = "$Env:USERPROFILE\.dotnet"
22+
$Env:PATH = "$Env:PATH;$DOTNET_ROOT;$DOTNET_ROOT\tools"
23+
dotnet tool install -g AWS.CodeArtifact.NuGet.CredentialProvider
24+
dotnet codeartifact-creds install
25+
- dotnet --list-sdks
26+
27+
build:
28+
commands:
29+
- |
30+
# See https://github.com/NuGet/NuGet.Client/pull/4259
31+
$Env:NUGET_EXPERIMENTAL_CHAIN_BUILD_RETRY_POLICY = "3,1000"
32+
33+
if ($Env:CODEARTIFACT_DOMAIN_NAME -and $Env:CODEARTIFACT_REPO_NAME) {
34+
$Env:CODEARTIFACT_URL=aws codeartifact get-repository-endpoint --domain $Env:CODEARTIFACT_DOMAIN_NAME --repository $Env:CODEARTIFACT_REPO_NAME --format maven --query repositoryEndpoint --output text
35+
$Env:CODEARTIFACT_NUGET_URL=aws codeartifact get-repository-endpoint --domain $Env:CODEARTIFACT_DOMAIN_NAME --repository $Env:CODEARTIFACT_REPO_NAME --format nuget --query repositoryEndpoint --output text
36+
$Env:CODEARTIFACT_AUTH_TOKEN=aws codeartifact get-authorization-token --domain $Env:CODEARTIFACT_DOMAIN_NAME --query authorizationToken --output text --duration-seconds 3600
37+
}
38+
39+
# Rider is very expensive (spikes our CI jobs to 50% CPU, so let it do the prep work in parallel, but run tests later
40+
./gradlew -PideProfileName="$Env:ALTERNATIVE_IDE_PROFILE_NAME" :plugin-amazonq:check --info --console plain --continue
41+
if ($LastExitCode -ne 0) {
42+
Write-Host "Command failed with exit code $LastExitCode"
43+
exit -1
44+
}
45+
# ./gradlew -PideProfileName="$Env:ALTERNATIVE_IDE_PROFILE_NAME" :plugin-toolkit:jetbrains-rider:check coverageReport --info --console plain
46+
47+
post_build:
48+
commands:
49+
- |
50+
$script:TEST_ARTIFACTS=Join-Path $env:TEMP testArtifacts
51+
$script:TEST_REPORTS=Join-Path $script:TEST_ARTIFACTS test-reports
52+
53+
function copyFolder($basedir, $subdir, $destdir) {
54+
$src = Join-Path "." -ChildPath $basedir | Join-Path -ChildPath $subdir
55+
$dest = Join-Path $destdir -ChildPath $basedir | Join-Path -ChildPath $subDir
56+
if( (Get-ChildItem $src -ErrorAction SilentlyContinue | Measure-Object).Count -ne 0) {
57+
Copy-Item $src $dest -Recurse -Force -ErrorAction SilentlyContinue
58+
}
59+
}
60+
61+
function copyArtifacts($root) {
62+
copyFolder $root "build/reports/" $script:TEST_ARTIFACTS
63+
copyFolder $root "build/idea-sandbox/system-test/log/" $script:TEST_ARTIFACTS
64+
copyFolder $root "build/test-results/test/" $script:TEST_REPORTS
65+
}
66+
67+
copyArtifacts "."
68+
Get-ChildItem -Directory | ForEach-Object { copyArtifacts $_.Name }
69+
70+
if(-Not($Env:CODEBUILD_BUILD_SUCCEEDING -eq "0" -Or $Env:CODE_COV_TOKEN -eq $null)) {
71+
$env:VCS_COMMIT_ID=$Env:CODEBUILD_RESOLVED_SOURCE_VERSION;
72+
$env:CI_BUILD_URL=[uri]::EscapeUriString($Env:CODEBUILD_BUILD_URL);
73+
$env:CI_BUILD_ID=$Env:CODEBUILD_BUILD_ID;
74+
.\codecov.exe -t $Env:CODE_COV_TOKEN `
75+
--flags unittest `
76+
-f "build/reports/jacoco/coverageReport/coverageReport.xml" `
77+
-c $Env:CODEBUILD_RESOLVED_SOURCE_VERSION
78+
}
79+
80+
reports:
81+
unit-test:
82+
files:
83+
- "**/*"
84+
base-directory: "$env:TEMP/testArtifacts/test-reports"
85+
discard-paths: yes
86+
87+
artifacts:
88+
base-directory: "$env:TEMP/testArtifacts"
89+
files:
90+
- "**/*"

buildspec/windowsTestsForCore.yml

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
version: 0.2
2+
3+
env:
4+
variables:
5+
CI: true
6+
LOCAL_ENV_RUN: true
7+
8+
phases:
9+
install:
10+
runtime-versions:
11+
java: corretto17
12+
13+
commands:
14+
- |
15+
if(-Not($Env:CODE_COV_TOKEN -eq $null)) {
16+
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;
17+
Invoke-WebRequest -Uri https://uploader.codecov.io/latest/windows/codecov.exe -Outfile codecov.exe
18+
}
19+
- dotnet --list-sdks
20+
- |
21+
$DOTNET_ROOT = "$Env:USERPROFILE\.dotnet"
22+
$Env:PATH = "$Env:PATH;$DOTNET_ROOT;$DOTNET_ROOT\tools"
23+
dotnet tool install -g AWS.CodeArtifact.NuGet.CredentialProvider
24+
dotnet codeartifact-creds install
25+
- dotnet --list-sdks
26+
27+
build:
28+
commands:
29+
- |
30+
# See https://github.com/NuGet/NuGet.Client/pull/4259
31+
$Env:NUGET_EXPERIMENTAL_CHAIN_BUILD_RETRY_POLICY = "3,1000"
32+
33+
if ($Env:CODEARTIFACT_DOMAIN_NAME -and $Env:CODEARTIFACT_REPO_NAME) {
34+
$Env:CODEARTIFACT_URL=aws codeartifact get-repository-endpoint --domain $Env:CODEARTIFACT_DOMAIN_NAME --repository $Env:CODEARTIFACT_REPO_NAME --format maven --query repositoryEndpoint --output text
35+
$Env:CODEARTIFACT_NUGET_URL=aws codeartifact get-repository-endpoint --domain $Env:CODEARTIFACT_DOMAIN_NAME --repository $Env:CODEARTIFACT_REPO_NAME --format nuget --query repositoryEndpoint --output text
36+
$Env:CODEARTIFACT_AUTH_TOKEN=aws codeartifact get-authorization-token --domain $Env:CODEARTIFACT_DOMAIN_NAME --query authorizationToken --output text --duration-seconds 3600
37+
}
38+
39+
# Rider is very expensive (spikes our CI jobs to 50% CPU, so let it do the prep work in parallel, but run tests later
40+
./gradlew -PideProfileName="$Env:ALTERNATIVE_IDE_PROFILE_NAME" :plugin-core:check --info --console plain --continue
41+
if ($LastExitCode -ne 0) {
42+
Write-Host "Command failed with exit code $LastExitCode"
43+
exit -1
44+
}
45+
# ./gradlew -PideProfileName="$Env:ALTERNATIVE_IDE_PROFILE_NAME" :plugin-toolkit:jetbrains-rider:check coverageReport --info --console plain
46+
47+
post_build:
48+
commands:
49+
- |
50+
$script:TEST_ARTIFACTS=Join-Path $env:TEMP testArtifacts
51+
$script:TEST_REPORTS=Join-Path $script:TEST_ARTIFACTS test-reports
52+
53+
function copyFolder($basedir, $subdir, $destdir) {
54+
$src = Join-Path "." -ChildPath $basedir | Join-Path -ChildPath $subdir
55+
$dest = Join-Path $destdir -ChildPath $basedir | Join-Path -ChildPath $subDir
56+
if( (Get-ChildItem $src -ErrorAction SilentlyContinue | Measure-Object).Count -ne 0) {
57+
Copy-Item $src $dest -Recurse -Force -ErrorAction SilentlyContinue
58+
}
59+
}
60+
61+
function copyArtifacts($root) {
62+
copyFolder $root "build/reports/" $script:TEST_ARTIFACTS
63+
copyFolder $root "build/idea-sandbox/system-test/log/" $script:TEST_ARTIFACTS
64+
copyFolder $root "build/test-results/test/" $script:TEST_REPORTS
65+
}
66+
67+
copyArtifacts "."
68+
Get-ChildItem -Directory | ForEach-Object { copyArtifacts $_.Name }
69+
70+
if(-Not($Env:CODEBUILD_BUILD_SUCCEEDING -eq "0" -Or $Env:CODE_COV_TOKEN -eq $null)) {
71+
$env:VCS_COMMIT_ID=$Env:CODEBUILD_RESOLVED_SOURCE_VERSION;
72+
$env:CI_BUILD_URL=[uri]::EscapeUriString($Env:CODEBUILD_BUILD_URL);
73+
$env:CI_BUILD_ID=$Env:CODEBUILD_BUILD_ID;
74+
.\codecov.exe -t $Env:CODE_COV_TOKEN `
75+
--flags unittest `
76+
-f "build/reports/jacoco/coverageReport/coverageReport.xml" `
77+
-c $Env:CODEBUILD_RESOLVED_SOURCE_VERSION
78+
}
79+
80+
reports:
81+
unit-test:
82+
files:
83+
- "**/*"
84+
base-directory: "$env:TEMP/testArtifacts/test-reports"
85+
discard-paths: yes
86+
87+
artifacts:
88+
base-directory: "$env:TEMP/testArtifacts"
89+
files:
90+
- "**/*"

0 commit comments

Comments
 (0)