Skip to content

Commit 29022bc

Browse files
committed
Add an integration test
1 parent 03c9b1c commit 29022bc

File tree

9 files changed

+803
-3
lines changed

9 files changed

+803
-3
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ release.properties
77
dependency-reduced-pom.xml
88
buildNumber.properties
99
.mvn/timing.properties
10+
*.log
1011

1112
# Avoid ignoring Maven wrapper jar file (.jar files are usually ignored)
1213
!/.mvn/wrapper/maven-wrapper.jar
@@ -29,4 +30,4 @@ buildNumber.properties
2930
# Ignore IntelliJ files
3031
.idea
3132
*.iml
32-
.vscode
33+
.vscode

it/Dockerfile-auditor

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
ARG SCANNER_VERSION=latest
2+
FROM sonarsource/sonar-scanner-cli:${SCANNER_VERSION} AS builder
3+
4+
FROM eclipse-temurin:21-jre-alpine
5+
6+
ARG SONAR_SCANNER_HOME=/opt/sonar-scanner
7+
ENV HOME=/tmp \
8+
SONAR_SCANNER_HOME=${SONAR_SCANNER_HOME} \
9+
XDG_CONFIG_HOME=/tmp \
10+
SONAR_USER_HOME=${SONAR_SCANNER_HOME}/.sonar \
11+
PATH=${SONAR_SCANNER_HOME}/bin:${PATH} \
12+
SRC_PATH=/usr/src \
13+
LANG=C.UTF-8 \
14+
LC_ALL=C.UTF-8 \
15+
PYTHONUNBUFFERED=1
16+
17+
WORKDIR /usr/src/myapp/it
18+
19+
USER root
20+
# Copy Scanner installation from builder image
21+
COPY --from=builder /opt/sonar-scanner /opt/sonar-scanner
22+
23+
24+
RUN apk update --no-cache && \
25+
apk add --update --no-cache -q curl gcc jq libffi-dev musl-dev openssl-dev python3 py3-requests shellcheck
26+
27+
RUN set -eux && \
28+
addgroup --gid 1000 scanner-cli && \
29+
adduser --uid 1000 --ingroup scanner-cli --disabled-password --no-create-home --gecos "" scanner-cli && \
30+
mkdir -p "${SRC_PATH}" "${SONAR_USER_HOME}" "${SONAR_USER_HOME}/cache" && \
31+
chown -R scanner-cli:scanner-cli "${SONAR_SCANNER_HOME}" "${SRC_PATH}" && \
32+
chmod -R 555 "${SONAR_SCANNER_HOME}" && \
33+
chmod -R 754 "${SRC_PATH}" "${SONAR_USER_HOME}"
34+
35+
USER scanner-cli
36+
COPY --chown=scanner-cli:scanner-cli it /usr/src/myapp/it

it/audit.sh

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#!/bin/sh -e
2+
3+
# ----------------------------------
4+
# Colors
5+
# ----------------------------------
6+
NOCOLOR='\033[0m'
7+
RED='\033[0;31m'
8+
GREEN='\033[0;32m'
9+
ORANGE='\033[0;33m'
10+
11+
# Function to get value from a property file
12+
# arg 1 = the property
13+
# arg 2 = the file path
14+
function prop {
15+
grep "${1}" ${2} | cut -d'=' -f2
16+
}
17+
18+
# Configure sonar-scanner
19+
export SONAR_HOST_URL="http://sonarqube:9000"
20+
export SONAR_ADMIN_LOGIN="admin"
21+
export SONAR_ADMIN_PWD="admin"
22+
23+
# Generate Analysis token
24+
echo "Generating analysis token..."
25+
# Use an UUID for token name. It's useful to launch the audit several time on the same SonarQube execution
26+
uuid=$(cat /proc/sys/kernel/random/uuid)
27+
export SONAR_TOKEN=$(curl -su "$SONAR_ADMIN_LOGIN:$SONAR_ADMIN_PWD" -XPOST "$SONAR_HOST_URL/api/user_tokens/generate?name=$uuid&type=GLOBAL_ANALYSIS_TOKEN" | jq -r '.token')
28+
echo $SONAR_TOKEN
29+
# Audit code
30+
echo "Launching scanner..."
31+
cd /usr/src/myapp/it
32+
sonar-scanner -X -Dsonar.qualitygate.wait 2>&1 | tee /tmp/scanner.log
33+
34+
if [ $? -ne 0 ]
35+
then
36+
echo "${RED}Error scanning Shell scripts${NOCOLOR}" >&2
37+
exit 1
38+
fi
39+
40+
# Check for warnings
41+
if grep -q "^WARN: " /tmp/scanner.log
42+
then
43+
echo -e "${ORANGE}Warnings found ${NOCOLOR}" >&2
44+
exit 1
45+
fi
46+
47+
# Sleep a little because SonarQube needs some time to ingest the audit results
48+
sleep 10
49+
50+
export SONAR_PROJECT_KEY=$(prop 'sonar.projectKey' sonar-project.properties)
51+
echo "SONAR_PROJECT_KEY: $SONAR_PROJECT_KEY"
52+
53+
# Check audit result
54+
echo "Checking result..."
55+
python3 << EOF
56+
from __future__ import print_function
57+
import requests
58+
import sys
59+
60+
r = requests.get('http://sonarqube:9000/api/issues/search?componentKeys=$SONAR_PROJECT_KEY:src/clanhb.f&statuses=OPEN', auth=('$SONAR_ADMIN_LOGIN', '$SONAR_ADMIN_PWD'))
61+
if r.status_code != 200:
62+
print('Invalid server response: ' + str(r.status_code), file=sys.stderr)
63+
sys.exit(1)
64+
65+
data = r.json()
66+
67+
if data['total'] != 100:
68+
print('Wrong total number of issues: ' + str(data['total']), file=sys.stderr)
69+
sys.exit(1)
70+
71+
issues = 0
72+
if 'f77-rules' in data['issues'][0]['rule'] and data['issues'][0]['line'] == 1:
73+
issues += 1
74+
75+
r = requests.get('http://sonarqube:9000/api/issues/search?componentKeys=$SONAR_PROJECT_KEY:src/clanhb.f90&statuses=OPEN', auth=('$SONAR_ADMIN_LOGIN', '$SONAR_ADMIN_PWD'))
76+
if r.status_code != 200:
77+
print('Invalid server response: ' + str(r.status_code), file=sys.stderr)
78+
sys.exit(1)
79+
80+
data = r.json()
81+
82+
if data['total'] != 197:
83+
print('Wrong total number of issues: ' + str(data['total']), file=sys.stderr)
84+
sys.exit(1)
85+
if 'f90-rules' in data['issues'][0]['rule'] and data['issues'][0]['line'] == 1:
86+
issues += 1
87+
88+
89+
sys.exit(0 if issues == 2 else 1)
90+
EOF

it/docker-compose.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
---
2+
services:
3+
sonarqube:
4+
image: sonarqube:${SONARQUBE_VERSION:-community}
5+
ports:
6+
- "9000:9000"
7+
environment:
8+
ES_JAVA_OPTS: "-Xms750m -Xmx750m"
9+
SONARQUBE_VERSION: ${SONARQUBE_VERSION:-community}
10+
security_opt:
11+
- seccomp:unconfined
12+
auditor:
13+
image: auditor:${SCANNER_VERSION:-latest}
14+
build:
15+
context: ..
16+
dockerfile: it/Dockerfile-auditor
17+
args:
18+
SCANNER_VERSION: ${SCANNER_VERSION:-latest}
19+
links:
20+
- sonarqube
21+
command: /bin/sh -e /usr/src/myapp/it/audit.sh
22+
environment:
23+
SCANNER_VERSION: ${SCANNER_VERSION:-latest}

it/it.sh

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#!/bin/bash
2+
3+
usage(){
4+
echo -e "\nUsage: $0 [sSh] \n"
5+
echo "-h : Display help"
6+
echo "-s [SONAR-SCANNER] : Take Sonar-scanner tag image from https://hub.docker.com/r/sonarsource/sonar-scanner-cli"
7+
echo "-S [SONARQUBE] : Take SonarQube tag image from https://hub.docker.com/_/sonarqube"
8+
}
9+
10+
OPTSTRING=":s:S:h"
11+
12+
while getopts ${OPTSTRING} opt; do
13+
case ${opt} in
14+
s)
15+
export SCANNER_VERSION=$OPTARG
16+
;;
17+
S)
18+
export SONARQUBE_VERSION=$OPTARG
19+
;;
20+
h)
21+
usage
22+
exit 0
23+
;;
24+
:)
25+
echo "Option -${OPTARG} requires an argument."
26+
usage
27+
exit 1
28+
;;
29+
?)
30+
echo "Invalid option: -${OPTARG}."
31+
usage
32+
exit 1
33+
;;
34+
esac
35+
done
36+
37+
38+
export SCRIPT_DIR=`dirname $0`
39+
40+
# Clean-up if needed
41+
echo "Cleanup..."
42+
docker-compose -f $SCRIPT_DIR/docker-compose.yml down
43+
44+
# Start containers
45+
echo "Starting SonarQube..."
46+
docker-compose -f $SCRIPT_DIR/docker-compose.yml up -d sonarqube
47+
CONTAINER_NAME=$(docker ps --format "{{.Names}}" | grep 'it-sonarqube-1.*' | head -1)
48+
# Wait for SonarQube to be up
49+
grep -q "SonarQube is operational" <(docker logs --follow --tail 0 $CONTAINER_NAME)
50+
echo "SonarQube started!"
51+
52+
# Copy the plugins
53+
MAVEN_VERSION=$(grep '<version>' $SCRIPT_DIR/../pom.xml | head -1 | sed 's/<\/\?version>//g'| awk '{print $1}')
54+
echo "Installing the plugin Icode version $MAVEN_VERSION"
55+
docker cp $SCRIPT_DIR/../target/sonar-icode-cnes-plugin-$MAVEN_VERSION.jar $CONTAINER_NAME:/opt/sonarqube/extensions/plugins
56+
# Restart SonarQube
57+
docker-compose -f $SCRIPT_DIR/docker-compose.yml restart sonarqube
58+
# Wait for SonarQube to be up
59+
grep -q "SonarQube is operational" <(docker logs --follow --tail 0 $CONTAINER_NAME)
60+
# Check plug-in installation
61+
docker exec -u root $CONTAINER_NAME bash -c "if grep -q Alpine /etc/issue; then apk update && apk add -q curl; fi"
62+
docker exec -u root $CONTAINER_NAME bash -c "if grep -q Ubuntu /etc/issue; then apt-get update && apt-get install -y curl; fi"
63+
if ! docker exec $CONTAINER_NAME curl -su admin:admin http://localhost:9000/api/plugins/installed | python -c '
64+
import sys
65+
import json
66+
plugins_count = 0
67+
plugins_expected = ["icode"]
68+
data = json.loads(sys.stdin.read())
69+
if "plugins" in data:
70+
for plugin in data["plugins"]:
71+
if plugin["key"] in plugins_expected:
72+
plugins_count += 1
73+
if plugins_count == len(plugins_expected):
74+
sys.exit(0)
75+
else:
76+
sys.exit(1)
77+
'
78+
then
79+
echo "Plugin not installed" >&2
80+
exit 1
81+
fi
82+
echo "Plugin successfully installed!"
83+
84+
# Audit code
85+
echo "Audit test scripts..."
86+
docker-compose -f $SCRIPT_DIR/docker-compose.yml up --build --exit-code-from auditor auditor
87+
AUDIT_STATUS=$?
88+
89+
# Delete containers
90+
echo "Cleanup..."
91+
docker-compose -f $SCRIPT_DIR/docker-compose.yml down
92+
93+
exit $AUDIT_STATUS

it/sonar-project.properties

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
sonar.projectKey=icode
2+
sonar.projectName=I-Code
3+
sonar.projectVersion=1.0
4+
sonar.sources=src
5+
sonar.scm.disabled=True

0 commit comments

Comments
 (0)