рд╕реЛрдирд╛рд░рдХреНрдпреВрдм рдПрдХ рдЦреБрд▓рд╛ рд╕реНрд░реЛрдд рдХреЛрдб рдЧреБрдгрд╕реНрддрд░ рдЖрд╢реНрд╡рд╛рд╕рди рдкреНрд▓реЗрдЯрдлрд░реНрдо рд╣реЛ рдЬрд╕рд▓реЗ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдЩ рднрд╛рд╖рд╛рд╣рд░реВрдХреЛ рд╡рд┐рд╕реНрддреГрдд рджрд╛рдпрд░рд╛рд▓рд╛рдИ рд╕рдорд░реНрдерди рдЧрд░реНрджрдЫ рд░ рдХреЛрдб рдбреБрдкреНрд▓рд┐рдХреЗрд╢рди, рдХреЛрдбрд┐рдЩ рдорд╛рдирдХ рдЕрдиреБрдкрд╛рд▓рди, рдкрд░реАрдХреНрд╖рдг рдХрднрд░реЗрдЬ, рдХреЛрдб рдЬрдЯрд┐рд▓рддрд╛, рд╕рдореНрднрд╛рд╡рд┐рдд рддреНрд░реБрдЯрд┐рд╣рд░реВ, рд░ рдердк рдЬрд╕реНрддрд╛ рдореЗрдЯреНрд░рд┐рдХреНрд╕рд╣рд░реВрдорд╛ рд░рд┐рдкреЛрд░реНрдЯрд╣рд░реВ рдкреНрд░рджрд╛рди рдЧрд░реНрджрдЫред рд╕реЛрдирд╛рд░рдХреНрдпреВрдмрд▓реЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдкрд░рд┐рдгрд╛рдорд╣рд░реВрд▓рд╛рдИ рд╕рд╣рдЬ рд░реВрдкрдорд╛ рдХрд▓реНрдкрдирд╛ рдЧрд░реНрджрдЫ рд░ рддрдкрд╛рдИрдВрд▓рд╛рдИ рд╕рдордпрд╕рдБрдЧреИ рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╡рд┐рдХрд╛рд╕ рдЧрддрд┐рд╢реАрд▓рддрд╛ рдЯреНрд░реНрдпрд╛рдХ рдЧрд░реНрди рдЕрдиреБрдорддрд┐ рджрд┐рдиреНрдЫред
рдХрд╛рд░реНрдп: рд╡рд┐рдХрд╛рд╕рдХрд░реНрддрд╛рд╣рд░реВрд▓рд╛рдИ SonarQube рдорд╛ рдЙрдиреАрд╣рд░реВрдХреЛ рд╕реНрд░реЛрдд рдХреЛрдбрдХреЛ рдЧреБрдгрд╕реНрддрд░ рдирд┐рдпрдиреНрддреНрд░рдг рд╕реНрдерд┐рддрд┐ рджреЗрдЦрд╛рдЙрдиреБрд╣реЛрд╕реНред
рддреНрдпрд╣рд╛рдБ рджреБрдИ рд╕рдорд╛рдзрд╛рдирд╣рд░реВ рдЫрдиреН:
- рд╕реЛрдирд╛рд░рдХреНрдпреВрдмрдорд╛ рд╕реНрд░реЛрдд рдХреЛрдб рдЧреБрдгрд╕реНрддрд░ рдЖрд╢реНрд╡рд╛рд╕рди рд╕реНрдерд┐рддрд┐ рдЬрд╛рдБрдЪ рдЧрд░реНрди рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЪрд▓рд╛рдЙрдиреБрд╣реЛрд╕реНред рдпрджрд┐ рд╕реЛрдирд╛рд░рдХреНрдпреВрдмрдХреЛ рд╕реНрд░реЛрдд рдХреЛрдб рдЧреБрдгрд╕реНрддрд░ рдЖрд╢реНрд╡рд╛рд╕рди рдЕрд╕рдлрд▓ рднрдпреЛ рднрдиреЗ, рдирд┐рд░реНрдорд╛рдг рдЕрд╕рдлрд▓ рдЧрд░реНрдиреБрд╣реЛрд╕реНред
- рдкрд░рд┐рдпреЛрдЬрдирд╛рдХреЛ рдореБрдЦреНрдп рдкреГрд╖реНрдардорд╛ рд╕реНрд░реЛрдд рдХреЛрдб рдЧреБрдгрд╕реНрддрд░ рдирд┐рдпрдиреНрддреНрд░рдг рд╕реНрдерд┐рддрд┐ рджреЗрдЦрд╛рдЙрдиреБрд╣реЛрд╕реНред
рд╕реЛрдирд╛рд░рдХреНрдпреВрдм рд╕реНрдерд╛рдкрдирд╛ рдЧрд░реНрджреИ
rpm рдкреНрдпрд╛рдХреЗрдЬрд╣рд░реВрдмрд╛рдЯ sonarqube рд╕реНрдерд╛рдкрдирд╛ рдЧрд░реНрди, рд╣рд╛рдореА рднрдгреНрдбрд╛рд░ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдиреЗрдЫреМрдВ .
CentOS 7 рдХреЛ рд▓рд╛рдЧрд┐ рд░рд┐рдкреЛрдЬрд┐рдЯрд░реА рдкреНрдпрд╛рдХреЗрдЬ рд╕реНрдерд╛рдкрдирд╛ рдЧрд░реМрдВред
yum install -y https://harbottle.gitlab.io/harbottle-main/7/x86_64/harbottle-main-release.rpmрд╕реЛрдирд╛рд░реНрдХреНрдпреБрдм рдЖрдлреИрдВ рд╕реНрдерд╛рдкрдирд╛ рдЧрд░реНрдиреБрд╣реЛрд╕реНред
yum install -y sonarqubeрд╕реНрдерд╛рдкрдирд╛рдХреЛ рдХреНрд░рдордорд╛, рдзреЗрд░реИрдЬрд╕реЛ рдкреНрд▓рдЧрдЗрдирд╣рд░реВ рд╕реНрдерд╛рдкрдирд╛ рд╣реБрдиреЗрдЫрдиреН, рддрд░ рддрдкрд╛рдИрдВрд▓реЗ findbugs рд░ pmd рд╕реНрдерд╛рдкрдирд╛ рдЧрд░реНрдиреБрдкрд░реНрдиреЗрдЫред
yum install -y sonarqube-findbugs sonarqube-pmdрд╕реЗрд╡рд╛ рд╕реБрд░реБ рдЧрд░реНрдиреБрд╣реЛрд╕реН рд░ рдпрд╕рд▓рд╛рдИ рд╕реНрдЯрд╛рд░реНрдЯрдЕрдкрдорд╛ рдердкреНрдиреБрд╣реЛрд╕реН
systemctl start sonarqube
systemctl enable sonarqubeрдпрджрд┐ рд▓реЛрдб рд╣реБрди рдзреЗрд░реИ рд╕рдордп рд▓рд╛рдЧреНрдЫ рднрдиреЗ, sonar.web.javaOpts рд╡рд┐рдХрд▓реНрдкрд╣рд░реВрдХреЛ рдЕрдиреНрддреНрдпрдорд╛ рдЕрдирд┐рдпрдорд┐рдд рд╕рдВрдЦреНрдпрд╛ рдЬреЗрдиреЗрд░реЗрдЯрд░ /dev/./urandom рдердкреНрдиреБрд╣реЛрд╕реНред
sonar.web.javaOpts=╨┤╤А╤Г╨│╨╕╨╡ ╨┐╨░╤А╨░╨╝╨╡╤В╤А╤Л -Djava.security.egd=file:/dev/urandomрд╕реЛрдирд╛рд░рдХреНрдпреВрдмрдорд╛ рд╕реНрд░реЛрдд рдХреЛрдб рдЧреБрдгрд╕реНрддрд░ рдирд┐рдпрдиреНрддреНрд░рдг рд╕реНрдерд┐рддрд┐ рдЬрд╛рдБрдЪ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдЪрд▓рд╛рдЙрдБрджреИред
рджреБрд░реНрднрд╛рдЧреНрдпрд╡рд╢, sonar-break-maven-plugin рдкреНрд▓рдЧрдЗрди рдХреЗрд╣реА рд╕рдордпрджреЗрдЦрд┐ рдЕрдкрдбреЗрдЯ рдЧрд░рд┐рдПрдХреЛ рдЫреИрдиред рддреНрдпрд╕реИрд▓реЗ, рдЖрдлреНрдиреИ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рд▓реЗрдЦреМрдВред
рдкрд░реАрдХреНрд╖рдгрдХреЛ рд▓рд╛рдЧрд┐ рд╣рд╛рдореА рднрдгреНрдбрд╛рд░ рдкреНрд░рдпреЛрдЧ рдЧрд░реНрдиреЗрдЫреМрдВ .
Gitlab рдорд╛ рдЖрдпрд╛рдд рдЧрд░реНрдиреБрд╣реЛрд╕реНред .gitlab-ci.yml рдлрд╛рдЗрд▓ рдердкреНрдиреБрд╣реЛрд╕реН:
variables:
MAVEN_OPTS: "-Dhttps.protocols=TLSv1.2 -Dmaven.repo.local=~/.m2/repository -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN -Dorg.slf4j.simpleLogger.showDateTime=true -Djava.awt.headless=true"
MAVEN_CLI_OPTS: "--batch-mode --errors --fail-at-end --show-version -DinstallAtEnd=true -DdeployAtEnd=true"
SONAR_HOST_URL: "http://172.26.9.226:9000"
LOGIN: "admin" # ╨╗╨╛╨│╨╕╨╜ sonarqube
PASSWORD: "admin" # ╨┐╨░╤А╨╛╨╗╤М sonarqube
cache:
paths:
- .m2/repository
build:
image: maven:3.3.9-jdk-8
stage: build
script:
- apt install -y jq || true
- mvn $MAVEN_CLI_OPTS -Dmaven.test.failure.ignore=true org.jacoco:jacoco-maven-plugin:0.8.5:prepare-agent clean verify org.jacoco:jacoco-maven-plugin:0.8.5:report
- mvn $MAVEN_CLI_OPTS -Dmaven.test.skip=true verify sonar:sonar -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.login=$LOGIN -Dsonar.password=$PASSWORD -Dsonar.gitlab.project_id=$CI_PROJECT_PATH -Dsonar.gitlab.commit_sha=$CI_COMMIT_SHA -Dsonar.gitlab.ref_name=$CI_COMMIT_REF_NAME
- export URL=$(cat target/sonar/report-task.txt | grep ceTaskUrl | cut -c11- ) #URL where report gets stored
- echo $URL
- |
while : ;do
curl -k -u "$LOGIN":"$PASSWORD" "$URL" -o analysis.txt
export status=$(cat analysis.txt | jq -r '.task.status') #Status as SUCCESS, CANCELED, IN_PROGRESS or FAILED
echo $status
if [ ${status} == "SUCCESS" ];then
echo "SONAR ANALYSIS SUCCESS";
break
fi
sleep 5
done
- curl -k -u "$LOGIN":"$PASSWORD" "$URL" -o analysis.txt
- export status=$(cat analysis.txt | jq -r '.task.status') #Status as SUCCESS, CANCELED or FAILED
- export analysisId=$(cat analysis.txt | jq -r '.task.analysisId') #Get the analysis Id
- |
if [ "$status" == "SUCCESS" ]; then
echo -e "SONAR ANALYSIS SUCCESSFUL...ANALYSING RESULTS";
curl -k -u "$LOGIN":"$PASSWORD" "$SONAR_HOST_URL/api/qualitygates/project_status?analysisId=$analysisId" -o result.txt; #Analysis result like critical, major and minor issues
export result=$(cat result.txt | jq -r '.projectStatus.status');
if [ "$result" == "ERROR" ];then
echo -e "91mSONAR RESULTS FAILED";
echo "$(cat result.txt | jq -r '.projectStatus.conditions')"; #prints the critical, major and minor violations
exit 1 #breaks the build for violations
else
echo -e "SONAR RESULTS SUCCESSFUL";
echo "$(cat result.txt | jq -r '.projectStatus.conditions')";
exit 0
fi
else
echo -e "e[91mSONAR ANALYSIS FAILEDe[0m";
exit 1 #breaks the build for failure in Step2
fi
tags:
- docker.gitlab-ci.yml рдлрд╛рдЗрд▓ рдЙрддреНрддрдо рдЫреИрдиред рдпрджрд┐ рд╕реЛрдирд╛рд░реНрдХреНрдпреБрдм рдЪреЗрдХ рдХрд╛рд░реНрдпрд╣рд░реВ "рд╕рдлрд▓рддрд╛" рд╕реНрдерд┐рддрд┐рд╕рдБрдЧ рдкреВрд░рд╛ рднрдПрдорд╛ рдореИрд▓реЗ рдпрд╕рд▓рд╛рдИ рдкрд░реАрдХреНрд╖рдг рдЧрд░реЗрдВред рдЕрд╣рд┐рд▓реЗрд╕рдореНрдо, рдЕрдиреНрдп рдХреБрдиреИ рдкрдирд┐ рд╕реНрдерд┐рддрд┐рд╣рд░реВ рдЫреИрдирдиреНред рдПрдХ рдкрдЯрдХ рдорд╕рдБрдЧ рдЕрдиреНрдп рд╕реНрдерд┐рддрд┐рд╣рд░реВ рднрдПрдкрдЫрд┐, рдо рдпрд╕ рдкреЛрд╕реНрдЯрдорд╛ .gitlab-ci.yml рдЕрдкрдбреЗрдЯ рдЧрд░реНрдиреЗрдЫреБред
рдкрд░рд┐рдпреЛрдЬрдирд╛рдХреЛ рдореБрдЦреНрдп рдкреГрд╖реНрдардорд╛ рд╕реНрд░реЛрдд рдХреЛрдб рдЧреБрдгрд╕реНрддрд░ рдирд┐рдпрдиреНрддреНрд░рдг рд╕реНрдерд┐рддрд┐ рдкреНрд░рджрд░реНрд╢рди рдЧрд░реНрджреИ
SonarQube рдкреНрд▓рдЧрдЗрди рд╕реНрдерд╛рдкрдирд╛ рдЧрд░реНрджреИ
yum install -y sonarqube-qualinsight-badgesрд╕реЛрдирд╛рд░рдХреНрдпреВрдмрдорд╛ рдЬрд╛рдиреБрд╣реЛрд╕реН рдареЗрдЧрд╛рдирд╛рдорд╛
рдирд┐рдпрдорд┐рдд рдкреНрд░рдпреЛрдЧрдХрд░реНрддрд╛ рд╕рд┐рд░реНрдЬрдирд╛ рдЧрд░реНрдиреБрд╣реЛрд╕реН, рдЙрджрд╛рд╣рд░рдгрдХрд╛ рд▓рд╛рдЧрд┐ "рдмреНрдпрд╛рдЬ"ред
рдпреЛ рдкреНрд░рдпреЛрдЧрдХрд░реНрддрд╛ рдирд╛рдо рдкреНрд░рдпреЛрдЧ рдЧрд░реЗрд░ SonarQube рдорд╛ рд▓рдЧ рдЗрди рдЧрд░реНрдиреБрд╣реЛрд╕реНред

"рдореЗрд░реЛ рдЦрд╛рддрд╛" рдорд╛ рдЬрд╛рдиреБрд╣реЛрд╕реН, рдПрдЙрдЯрд╛ рдирдпрд╛рдБ рдЯреЛрдХрди рд╕рд┐рд░реНрдЬрдирд╛ рдЧрд░реНрдиреБрд╣реЛрд╕реН, рдЙрджрд╛рд╣рд░рдгрдХрд╛ рд▓рд╛рдЧрд┐, "read_all_repository" рднрдирд┐рдиреЗ рд░ "Genereate" рдорд╛ рдХреНрд▓рд┐рдХ рдЧрд░реНрдиреБрд╣реЛрд╕реНред

рд╣рд╛рдореАрд▓реЗ рджреЗрдЦреНрдпреМрдВ рдХрд┐ рдПрдЙрдЯрд╛ рдЯреЛрдХрди рджреЗрдЦрд╛ рдкрд░реЗрдХреЛ рдЫред рдпреЛ рдПрдХ рдкрдЯрдХ рдорд╛рддреНрд░ рджреЗрдЦрд╛ рдкрд░реНрдиреЗрдЫред
рдкреНрд░рд╢рд╛рд╕рдХрдХреЛ рд░реВрдкрдорд╛ рд▓рдЧ рдЗрди рдЧрд░реНрдиреБрд╣реЛрд╕реНред
рдХрдиреНрдлрд┐рдЧрд░реЗрд╕рди -> SVG рдмреНрдпрд╛рдЬрд╣рд░реВрдорд╛ рдЬрд╛рдиреБрд╣реЛрд╕реН

рдпреЛ рдЯреЛрдХрдирд▓рд╛рдИ "рдЧрддрд┐рд╡рд┐рдзрд┐ рдмреНрдпрд╛рдЬ рдЯреЛрдХрди" рдлрд┐рд▓реНрдбрдорд╛ рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдЧрд░реНрдиреБрд╣реЛрд╕реН рд░ рдмрдЪрдд рдмрдЯрдирдорд╛ рдХреНрд▓рд┐рдХ рдЧрд░реНрдиреБрд╣реЛрд╕реНред

рдкреНрд░рд╢рд╛рд╕рди -> рд╕реБрд░рдХреНрд╖рд╛ -> рдЕрдиреБрдорддрд┐ рдЯреЗрдореНрдкреНрд▓реЗрдЯрд╣рд░реВ -> рдкреВрд░реНрд╡рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдЯреЗрдореНрдкреНрд▓реЗрдЯ (рд░ рддрдкрд╛рдИрдВрд╕рдБрдЧ рд╣реБрди рд╕рдХреНрдиреЗ рдЕрдиреНрдп рдЯреЗрдореНрдкреНрд▓реЗрдЯрд╣рд░реВ) рдорд╛ рдЬрд╛рдиреБрд╣реЛрд╕реНред
рдмреНрдпрд╛рдЬ рдкреНрд░рдпреЛрдЧрдХрд░реНрддрд╛рд▓реЗ "рдмреНрд░рд╛рдЙрдЬ" рдЪреЗрдХрдмрдХреНрд╕рдорд╛ рдЪрд┐рдиреНрд╣ рд▓рдЧрд╛рдПрдХреЛ рд╣реБрдиреБрдкрд░реНрдЫред
рдкрд░реАрдХреНрд╖рдг рдЧрд░реНрджреИред
рдкрд░рд┐рдпреЛрдЬрдирд╛рд▓рд╛рдИ рдЙрджрд╛рд╣рд░рдгрдХреЛ рд░реВрдкрдорд╛ рд▓рд┐рдФрдВ .
рдпреЛ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдЖрдпрд╛рдд рдЧрд░реМрдВред
рдирд┐рдореНрди рд╕рд╛рдордЧреНрд░реАрд╣рд░реВ рд╕рд╣рд┐рдд рдкрд░рд┐рдпреЛрдЬрдирд╛рдХреЛ рд░реВрдЯрдорд╛ .gitlab-ci.yml рдлрд╛рдЗрд▓ рдердкреНрдиреБрд╣реЛрд╕реНред
variables:
MAVEN_OPTS: "-Dhttps.protocols=TLSv1.2 -Dmaven.repo.local=~/.m2/repository -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN -Dorg.slf4j.simpleLogger.showDateTime=true -Djava.awt.headless=true"
MAVEN_CLI_OPTS: "--batch-mode --errors --fail-at-end --show-version -DinstallAtEnd=true -DdeployAtEnd=true"
SONAR_HOST_URL: "http://172.26.9.115:9000"
LOGIN: "admin" # ╨╗╨╛╨│╨╕╨╜ sonarqube
PASSWORD: "admin" # ╨┐╨░╤А╨╛╨╗╤М sonarqube
cache:
paths:
- .m2/repository
build:
image: maven:3.3.9-jdk-8
stage: build
script:
- mvn $MAVEN_CLI_OPTS -Dmaven.test.failure.ignore=true org.jacoco:jacoco-maven-plugin:0.8.5:prepare-agent clean verify org.jacoco:jacoco-maven-plugin:0.8.5:report
- mvn $MAVEN_CLI_OPTS -Dmaven.test.skip=true verify sonar:sonar -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.login=$LOGIN -Dsonar.password=$PASSWORD -Dsonar.gitlab.project_id=$CI_PROJECT_PATH -Dsonar.gitlab.commit_sha=$CI_COMMIT_SHA -Dsonar.gitlab.ref_name=$CI_COMMIT_REF_NAME
tags:
- dockerрд╕реЛрдирд╛рд░рдХреНрдпреВрдмрдорд╛ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдпрд╕реНрддреЛ рджреЗрдЦрд┐рдиреЗрдЫ:

README.md рдорд╛ рдкреНрдпрд╛рдХреЗрдЬрд╣рд░реВ рдердкреНрдиреБрд╣реЛрд╕реН рд░ рддрд┐рдиреАрд╣рд░реВ рдпрд╕реНрддреЛ рджреЗрдЦрд┐рдиреЗрдЫрдиреН:

рдмреНрдпрд╛рдЬрд╣рд░реВ рдкреНрд░рджрд░реНрд╢рди рдЧрд░реНрдиреЗ рдХреЛрдб рдпрд╕реНрддреЛ рджреЗрдЦрд┐рдиреНрдЫ:

рдмреНрдпрд╛рдЬ рдкреНрд░рджрд░реНрд╢рди рд╕реНрдЯреНрд░рд┐рдЩ рдкрд╛рд░реНрд╕ рдЧрд░реНрджреИ:
[](http://172.26.9.115:9000/dashboard?id=com.github.jitpack%3Amaven-simple)
[](http://172.26.9.115:9000/dashboard?id=id-╨┐╤А╨╛╨╡╨║╤В╨░)
[](http://172.26.9.115:9000/dashboard?id=com.github.jitpack%3Amaven-simple)
[](http://172.26.9.115:9000/dashboard?id=id-╨┐╤А╨╛╨╡╨║╤В╨░)рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреБрдЮреНрдЬреА рд░ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдЖрдИрдбреА рдХрд╣рд╛рдБрдмрд╛рдЯ рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрдиреЗ/рдЬрд╛рдБрдЪ рдЧрд░реНрдиреЗред
рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреБрдЮреНрдЬреА рддрд▓ рджрд╛рдпрд╛рдБрдкрдЯреНрдЯрд┐ рдЕрд╡рд╕реНрдерд┐рдд рдЫред URL рдорд╛ рдкрд░рд┐рдпреЛрдЬрдирд╛ ID рд╕рдорд╛рд╡реЗрд╢ рдЫред

рдореЗрдЯреНрд░рд┐рдХреНрд╕ рдкреНрд░рд╛рдкреНрдд рдЧрд░реНрдиреЗ рд╡рд┐рдХрд▓реНрдкрд╣рд░реВ рдирд┐рдореНрди рд╣реБрди рд╕рдХреНрдЫрдиреН .
рд╕реБрдзрд╛рд░ рд░ рдмрдЧ рд╕рдорд╛рдзрд╛рдирдХрд╛ рд▓рд╛рдЧрд┐ рд╕рдмреИ рдкреБрд▓ рдЕрдиреБрд░реЛрдзрд╣рд░реВ .
рд╕реЛрдирд╛рд░рдХреНрдпреВрдмрдХреЛ рдмрд╛рд░реЗрдорд╛ рдЯреЗрд▓рд┐рдЧреНрд░рд╛рдо рдЪреНрдпрд╛рдЯ
DevSecOps тАФ рд╕реБрд░рдХреНрд╖рд┐рдд DevOps рдмрд╛рд░реЗ рдЯреЗрд▓рд┐рдЧреНрд░рд╛рдо рдЪреНрдпрд╛рдЯ
рд╕реНрд░реЛрдд: www.habr.com
