ci: stabilize Jenkins jobs and mobile pipeline
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
---
|
||||
- defaults:
|
||||
name: global
|
||||
project_folder: /workspace/otus-autotests
|
||||
project_folder: /workspace/hw8
|
||||
test_image_tag: "1.0.0"
|
||||
build_keep: 40
|
||||
|
||||
@@ -5,6 +5,18 @@ pipeline {
|
||||
ansiColor('xterm')
|
||||
}
|
||||
stages {
|
||||
stage('Prepare Metadata') {
|
||||
steps {
|
||||
script {
|
||||
wrap([$class: 'BuildUser']) {
|
||||
env.RUN_TRIGGER_USER = env.BUILD_USER_ID ?: env.BUILD_USER ?: 'system'
|
||||
env.RUN_TRIGGER_NAME = env.BUILD_USER ?: env.BUILD_USER_ID ?: 'system'
|
||||
}
|
||||
currentBuild.displayName = "#${env.BUILD_NUMBER} infra"
|
||||
currentBuild.description = "by=${env.RUN_TRIGGER_NAME}"
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Check Docker & Registry') {
|
||||
steps {
|
||||
sh '''
|
||||
@@ -17,13 +29,12 @@ pipeline {
|
||||
'''
|
||||
}
|
||||
}
|
||||
stage('Check Sources') {
|
||||
stage('Check Job Configs') {
|
||||
steps {
|
||||
sh '''
|
||||
set -eux
|
||||
test -f /workspace/otus-autotests/homework_4/pom.xml
|
||||
test -f /workspace/otus-autotests/hw7/pom.xml
|
||||
test -f /workspace/otus-autotests/hw8/config/jobs/global.yaml
|
||||
HW8_ROOT_PATH="${HW8_ROOT:-/workspace/hw8}"
|
||||
test -f "${HW8_ROOT_PATH}/config/jobs/global.yaml"
|
||||
'''
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,18 @@ pipeline {
|
||||
ansiColor('xterm')
|
||||
}
|
||||
stages {
|
||||
stage('Prepare Metadata') {
|
||||
steps {
|
||||
script {
|
||||
wrap([$class: 'BuildUser']) {
|
||||
env.RUN_TRIGGER_USER = env.BUILD_USER_ID ?: env.BUILD_USER ?: 'system'
|
||||
env.RUN_TRIGGER_NAME = env.BUILD_USER ?: env.BUILD_USER_ID ?: 'system'
|
||||
}
|
||||
currentBuild.displayName = "#${env.BUILD_NUMBER} jjb"
|
||||
currentBuild.description = "by=${env.RUN_TRIGGER_NAME}; jjbPath=${params.JJB_PATH}"
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Validate Input') {
|
||||
steps {
|
||||
sh '''
|
||||
|
||||
@@ -5,19 +5,47 @@ pipeline {
|
||||
ansiColor('xterm')
|
||||
}
|
||||
stages {
|
||||
stage('Prepare Metadata') {
|
||||
steps {
|
||||
script {
|
||||
wrap([$class: 'BuildUser']) {
|
||||
env.RUN_TRIGGER_USER = env.BUILD_USER_ID ?: env.BUILD_USER ?: 'system'
|
||||
env.RUN_TRIGGER_NAME = env.BUILD_USER ?: env.BUILD_USER_ID ?: 'system'
|
||||
}
|
||||
currentBuild.displayName = "#${env.BUILD_NUMBER} api"
|
||||
currentBuild.description =
|
||||
"by=${env.RUN_TRIGGER_NAME}; repo=${params.QA_REPO_URL}; ref=${params.QA_REPO_REF}"
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Run API Tests In Docker') {
|
||||
steps {
|
||||
sh '''
|
||||
set -eux
|
||||
rm -rf ./sources
|
||||
git clone "${QA_REPO_URL}" ./sources
|
||||
git -C ./sources checkout "${QA_REPO_REF}"
|
||||
GIT_SHA="$(git -C ./sources rev-parse --short HEAD)"
|
||||
|
||||
rm -rf ./artifacts
|
||||
mkdir -p ./artifacts
|
||||
{
|
||||
echo "job=${JOB_NAME}"
|
||||
echo "build=${BUILD_NUMBER}"
|
||||
echo "trigger_user=${RUN_TRIGGER_USER}"
|
||||
echo "trigger_name=${RUN_TRIGGER_NAME}"
|
||||
echo "qa_repo_url=${QA_REPO_URL}"
|
||||
echo "qa_repo_ref=${QA_REPO_REF}"
|
||||
echo "qa_repo_sha=${GIT_SHA}"
|
||||
echo "timestamp_utc=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||
} > ./artifacts/run-info.txt
|
||||
|
||||
CID="$(docker create localhost:5005/otus/test-api:1.0.0 bash -lc "set -e; cd /workspace; mvn -f citrus-tests/pom.xml test")"
|
||||
cleanup_container() {
|
||||
docker rm -f "${CID}" >/dev/null 2>&1 || true
|
||||
}
|
||||
trap cleanup_container EXIT INT TERM
|
||||
tar -C /workspace/otus-autotests/homework_4 -cf - . | docker cp - "${CID}:/workspace"
|
||||
tar -C ./sources -cf - . | docker cp - "${CID}:/workspace"
|
||||
set +e
|
||||
docker start -a "${CID}"
|
||||
TEST_RC=$?
|
||||
@@ -32,7 +60,7 @@ pipeline {
|
||||
post {
|
||||
always {
|
||||
junit allowEmptyResults: true, testResults: 'artifacts/citrus-target/surefire-reports/*.xml'
|
||||
archiveArtifacts allowEmptyArchive: true, artifacts: 'artifacts/citrus-target/**'
|
||||
archiveArtifacts allowEmptyArchive: true, artifacts: 'artifacts/run-info.txt,artifacts/citrus-target/**'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,13 +5,61 @@ pipeline {
|
||||
ansiColor('xterm')
|
||||
}
|
||||
stages {
|
||||
stage('Prepare Metadata') {
|
||||
steps {
|
||||
script {
|
||||
wrap([$class: 'BuildUser']) {
|
||||
env.RUN_TRIGGER_USER = env.BUILD_USER_ID ?: env.BUILD_USER ?: 'system'
|
||||
env.RUN_TRIGGER_NAME = env.BUILD_USER ?: env.BUILD_USER_ID ?: 'system'
|
||||
}
|
||||
currentBuild.displayName = "#${env.BUILD_NUMBER} mobile"
|
||||
currentBuild.description =
|
||||
"by=${env.RUN_TRIGGER_NAME}; repo=${params.MOBILE_REPO_URL}; ref=${params.MOBILE_REPO_REF}; emulators=${params.MOBILE_MAX_EMULATORS}; junit=${params.JUNIT_PARALLELISM}; order=${params.TEST_CLASSES_ORDER}; rerun=${params.SUREFIRE_RERUN_FAILING}"
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Prepare Workspace') {
|
||||
steps {
|
||||
sh '''
|
||||
set -eux
|
||||
rm -rf ./project
|
||||
mkdir -p ./project
|
||||
cp -a /workspace/otus-autotests/hw7/. ./project/
|
||||
git clone "${MOBILE_REPO_URL}" ./project
|
||||
git -C ./project checkout "${MOBILE_REPO_REF}"
|
||||
GIT_SHA="$(git -C ./project rev-parse --short HEAD)"
|
||||
if ! grep -q "<artifactId>allure-junit5</artifactId>" ./project/pom.xml; then
|
||||
awk -v ver="${ALLURE_ADAPTER_VERSION}" '
|
||||
index($0, "</dependencies>") && !done {
|
||||
print " <dependency>"
|
||||
print " <groupId>io.qameta.allure</groupId>"
|
||||
print " <artifactId>allure-junit5</artifactId>"
|
||||
print " <version>" ver "</version>"
|
||||
print " <scope>test</scope>"
|
||||
print " </dependency>"
|
||||
done=1
|
||||
}
|
||||
{ print }
|
||||
' ./project/pom.xml > ./project/pom.xml.tmp
|
||||
mv ./project/pom.xml.tmp ./project/pom.xml
|
||||
fi
|
||||
mkdir -p ./project/target/allure-results
|
||||
{
|
||||
echo "job=${JOB_NAME}"
|
||||
echo "build=${BUILD_NUMBER}"
|
||||
echo "trigger_user=${RUN_TRIGGER_USER}"
|
||||
echo "trigger_name=${RUN_TRIGGER_NAME}"
|
||||
echo "mobile_repo_url=${MOBILE_REPO_URL}"
|
||||
echo "mobile_repo_ref=${MOBILE_REPO_REF}"
|
||||
echo "mobile_repo_sha=${GIT_SHA}"
|
||||
echo "app_url=${APP_URL}"
|
||||
echo "mobile_max_emulators=${MOBILE_MAX_EMULATORS}"
|
||||
echo "junit_parallelism=${JUNIT_PARALLELISM}"
|
||||
echo "test_classes_order=${TEST_CLASSES_ORDER}"
|
||||
echo "surefire_rerun_failing=${SUREFIRE_RERUN_FAILING}"
|
||||
echo "db_url=${DB_URL}"
|
||||
echo "db_user=${DB_USER}"
|
||||
echo "reservation_owner=${RESERVATION_OWNER}"
|
||||
echo "timestamp_utc=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||
} > ./project/run-info.txt
|
||||
'''
|
||||
}
|
||||
}
|
||||
@@ -20,7 +68,8 @@ pipeline {
|
||||
dir('project') {
|
||||
sh '''
|
||||
set -eux
|
||||
COMPOSE_FILE="/workspace/otus-autotests/hw8/config/compose/mobile-ci.compose.yml"
|
||||
HW8_ROOT_PATH="${HW8_ROOT:-/workspace/hw8}"
|
||||
COMPOSE_FILE="${HW8_ROOT_PATH}/config/compose/mobile-ci.compose.yml"
|
||||
if docker compose version >/dev/null 2>&1; then
|
||||
compose_cmd() { PROJECT_DIR="$PWD" docker compose -f "${COMPOSE_FILE}" "$@"; }
|
||||
elif docker-compose version >/dev/null 2>&1; then
|
||||
@@ -30,11 +79,32 @@ pipeline {
|
||||
exit 1
|
||||
fi
|
||||
export COMPOSE_PROJECT_NAME=mobileci
|
||||
compose_cmd down -v --remove-orphans || true
|
||||
compose_cmd up -d wiremock android-emulator-1 android-emulator-2
|
||||
MAX_EMULATORS="${MOBILE_MAX_EMULATORS:-1}"
|
||||
if ! [ "${MAX_EMULATORS}" -eq "${MAX_EMULATORS}" ] 2>/dev/null; then
|
||||
echo "Invalid MOBILE_MAX_EMULATORS='${MAX_EMULATORS}', expected integer"
|
||||
exit 1
|
||||
fi
|
||||
if [ "${MAX_EMULATORS}" -lt 1 ] || [ "${MAX_EMULATORS}" -gt 2 ]; then
|
||||
echo "Invalid MOBILE_MAX_EMULATORS='${MAX_EMULATORS}', expected 1 or 2"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SERVICES="wiremock android-emulator-1"
|
||||
if [ "${MAX_EMULATORS}" -ge 2 ]; then
|
||||
SERVICES="${SERVICES} android-emulator-2"
|
||||
fi
|
||||
|
||||
compose_cmd down -v --remove-orphans || true
|
||||
compose_cmd up -d ${SERVICES}
|
||||
EMULATORS=""
|
||||
SELECTED=0
|
||||
for service in android-emulator-1 android-emulator-2; do
|
||||
if [ "${service}" = "android-emulator-2" ] && [ "${MAX_EMULATORS}" -lt 2 ]; then
|
||||
continue
|
||||
fi
|
||||
if [ "${SELECTED}" -ge "${MAX_EMULATORS}" ]; then
|
||||
break
|
||||
fi
|
||||
cid="$(compose_cmd ps -q "$service")"
|
||||
if [ -z "${cid}" ]; then
|
||||
echo "Container for ${service} not found, skipping"
|
||||
@@ -55,6 +125,7 @@ pipeline {
|
||||
EMULATORS="${EMULATORS},"
|
||||
fi
|
||||
EMULATORS="${EMULATORS}${service}|http://${service}:4723|Android Emulator|${APP_URL}"
|
||||
SELECTED=$((SELECTED + 1))
|
||||
else
|
||||
echo "Service ${service} is not healthy in time, excluding from test run"
|
||||
docker logs "${cid}" || true
|
||||
@@ -76,40 +147,258 @@ pipeline {
|
||||
dir('project') {
|
||||
sh '''
|
||||
set -eux
|
||||
rm -rf ./target
|
||||
rm -rf ./target ./target-run
|
||||
MOBILE_EMULATORS_VALUE="$(cat ./.mobile_emulators.txt)"
|
||||
EMULATOR_ENTRIES_COUNT="$(printf '%s' "${MOBILE_EMULATORS_VALUE}" | awk -F, '{print NF}')"
|
||||
DOCKER_NETWORK_ARG="--network mobileci_default"
|
||||
if [ "${EMULATOR_ENTRIES_COUNT}" -eq 1 ]; then
|
||||
SINGLE_SERVICE="$(printf '%s' "${MOBILE_EMULATORS_VALUE}" | cut -d'|' -f1)"
|
||||
if [ "${SINGLE_SERVICE}" = "android-emulator-1" ] || [ "${SINGLE_SERVICE}" = "android-emulator-2" ]; then
|
||||
SINGLE_EMULATOR_CID="$(docker ps -q --filter "name=mobileci-${SINGLE_SERVICE}" | head -n1 || true)"
|
||||
if [ -n "${SINGLE_EMULATOR_CID}" ]; then
|
||||
DOCKER_NETWORK_ARG="--network container:${SINGLE_EMULATOR_CID}"
|
||||
MOBILE_EMULATORS_VALUE="$(printf '%s' "${MOBILE_EMULATORS_VALUE}" | awk -F'|' 'BEGIN { OFS="|" } { $2="http://127.0.0.1:4723"; print $1, $2, $3, $4 }')"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
DB_PASSWORD_EFFECTIVE="${DB_PASSWORD:-${MOBILE_DB_PASSWORD:-}}"
|
||||
if [ -z "${DB_PASSWORD_EFFECTIVE}" ]; then
|
||||
echo "DB password is not set. Provide DB_PASSWORD job parameter or MOBILE_DB_PASSWORD env variable."
|
||||
exit 1
|
||||
fi
|
||||
CID="$(docker create \
|
||||
--network mobileci_default \
|
||||
-e DB_URL="${DB_URL:-}" \
|
||||
-e DB_USER="${DB_USER:-}" \
|
||||
-e DB_PASSWORD="${DB_PASSWORD_EFFECTIVE}" \
|
||||
-e APP_URL="${APP_URL:-}" \
|
||||
|
||||
# Validate Appium endpoints from the same Docker network as test container.
|
||||
if ! docker run --rm \
|
||||
${DOCKER_NETWORK_ARG} \
|
||||
-e MOBILE_EMULATORS="${MOBILE_EMULATORS_VALUE}" \
|
||||
-e WISHLISTS_USERNAME="${WISHLISTS_USERNAME:-}" \
|
||||
-e WISHLISTS_PASSWORD="${WISHLISTS_PASSWORD:-}" \
|
||||
-e GIFTS_USERNAME="${GIFTS_USERNAME:-}" \
|
||||
-e GIFTS_PASSWORD="${GIFTS_PASSWORD:-}" \
|
||||
-e RESERVATION_USERNAME="${RESERVATION_USERNAME:-}" \
|
||||
-e RESERVATION_PASSWORD="${RESERVATION_PASSWORD:-}" \
|
||||
-e RESERVATION_OWNER="${RESERVATION_OWNER:-}" \
|
||||
localhost:5005/otus/test-mobile:1.0.0 \
|
||||
bash -lc "set -e; cd /workspace; timeout 1800s mvn -Dallure.results.directory=target/allure-results test")"
|
||||
cleanup_container() {
|
||||
bash -lc '
|
||||
set -euo pipefail
|
||||
IFS="," read -ra TARGETS <<< "${MOBILE_EMULATORS}"
|
||||
for target in "${TARGETS[@]}"; do
|
||||
endpoint="$(echo "${target}" | cut -d"|" -f2)"
|
||||
if [ -z "${endpoint}" ]; then
|
||||
echo "Invalid MOBILE_EMULATORS entry: ${target}"
|
||||
exit 1
|
||||
fi
|
||||
ready="false"
|
||||
for i in $(seq 1 60); do
|
||||
if curl -fsS "${endpoint}/status" >/dev/null 2>&1; then
|
||||
ready="true"
|
||||
break
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
if [ "${ready}" != "true" ]; then
|
||||
echo "Appium endpoint is not reachable from test container: ${endpoint}"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
'; then
|
||||
echo "Appium preflight failed. Dumping emulator logs."
|
||||
for service in android-emulator-1 android-emulator-2; do
|
||||
cid="$(docker ps -q --filter "name=mobileci-${service}" | head -n1 || true)"
|
||||
if [ -n "${cid}" ]; then
|
||||
echo "--- logs for ${service} (${cid}) ---"
|
||||
docker logs --tail 200 "${cid}" || true
|
||||
fi
|
||||
done
|
||||
exit 1
|
||||
fi
|
||||
|
||||
run_single_class() {
|
||||
class_name="$1"
|
||||
attempt="$2"
|
||||
class_key="$(echo "${class_name}" | sed 's/[^a-zA-Z0-9._-]/_/g')"
|
||||
attempt_dir="./target-run/${class_key}/attempt-${attempt}"
|
||||
mkdir -p "${attempt_dir}"
|
||||
|
||||
CID="$(docker create \
|
||||
${DOCKER_NETWORK_ARG} \
|
||||
-e DB_URL="${DB_URL:-}" \
|
||||
-e DB_USER="${DB_USER:-}" \
|
||||
-e DB_PASSWORD="${DB_PASSWORD_EFFECTIVE}" \
|
||||
-e APP_URL="${APP_URL:-}" \
|
||||
-e MOBILE_EMULATORS="${MOBILE_EMULATORS_VALUE}" \
|
||||
-e WISHLISTS_USERNAME="${WISHLISTS_USERNAME:-}" \
|
||||
-e WISHLISTS_PASSWORD="${WISHLISTS_PASSWORD:-}" \
|
||||
-e GIFTS_USERNAME="${GIFTS_USERNAME:-}" \
|
||||
-e GIFTS_PASSWORD="${GIFTS_PASSWORD:-}" \
|
||||
-e RESERVATION_USERNAME="${RESERVATION_USERNAME:-}" \
|
||||
-e RESERVATION_PASSWORD="${RESERVATION_PASSWORD:-}" \
|
||||
-e RESERVATION_OWNER="${RESERVATION_OWNER:-}" \
|
||||
localhost:5005/otus/test-mobile:1.0.0 \
|
||||
bash -lc "set -e; cd /workspace; timeout 1800s mvn -Dallure.version=${ALLURE_ADAPTER_VERSION} -Djunit.jupiter.execution.parallel.enabled=false -Djunit.jupiter.execution.parallel.config.fixed.parallelism=${JUNIT_PARALLELISM:-1} -Dtest=${class_name} -Dsurefire.rerunFailingTestsCount=${SUREFIRE_RERUN_FAILING:-0} -Dallure.results.directory=target/allure-results test")"
|
||||
|
||||
tar -C "$PWD" -cf - . | docker cp - "${CID}:/workspace"
|
||||
set +e
|
||||
docker start -a "${CID}"
|
||||
class_rc=$?
|
||||
set -e
|
||||
docker cp "${CID}:/workspace/target" "${attempt_dir}/target" || true
|
||||
docker rm -f "${CID}" >/dev/null 2>&1 || true
|
||||
return "${class_rc}"
|
||||
}
|
||||
trap cleanup_container EXIT INT TERM
|
||||
tar -C "$PWD" -cf - . | docker cp - "${CID}:/workspace"
|
||||
set +e
|
||||
docker start -a "${CID}"
|
||||
TEST_RC=$?
|
||||
docker cp "${CID}:/workspace/target" "./target" || true
|
||||
trap - EXIT INT TERM
|
||||
docker rm -f "${CID}" || true
|
||||
|
||||
collect_attempt_artifacts() {
|
||||
src_dir="$1"
|
||||
mkdir -p ./target/allure-results ./target/surefire-reports
|
||||
if [ -d "${src_dir}/allure-results" ]; then
|
||||
cp -a "${src_dir}/allure-results/." ./target/allure-results/ || true
|
||||
fi
|
||||
if [ -d "${src_dir}/surefire-reports" ]; then
|
||||
cp -a "${src_dir}/surefire-reports/." ./target/surefire-reports/ || true
|
||||
fi
|
||||
}
|
||||
|
||||
if [ -n "${TEST_CLASSES_ORDER:-}" ]; then
|
||||
printf '%s\n' "${TEST_CLASSES_ORDER}" | tr ',' '\n' > .test-classes.txt
|
||||
else
|
||||
cat > .test-classes.txt <<'EOF'
|
||||
ru.otus.mobile.tests.WishlistsTest
|
||||
ru.otus.mobile.tests.GiftsTest
|
||||
ru.otus.mobile.tests.ReservationTest
|
||||
EOF
|
||||
fi
|
||||
|
||||
TEST_RC=0
|
||||
MAX_CLASS_ATTEMPTS=2
|
||||
while IFS= read -r raw_class; do
|
||||
class_name="$(echo "${raw_class}" | xargs)"
|
||||
if [ -z "${class_name}" ]; then
|
||||
continue
|
||||
fi
|
||||
CLASS_OK=0
|
||||
LAST_ATTEMPT_DIR=""
|
||||
for attempt in $(seq 1 "${MAX_CLASS_ATTEMPTS}"); do
|
||||
echo "Running ${class_name} (attempt ${attempt}/${MAX_CLASS_ATTEMPTS})"
|
||||
if run_single_class "${class_name}" "${attempt}"; then
|
||||
CLASS_OK=1
|
||||
LAST_ATTEMPT_DIR="./target-run/$(echo "${class_name}" | sed 's/[^a-zA-Z0-9._-]/_/g')/attempt-${attempt}/target"
|
||||
collect_attempt_artifacts "${LAST_ATTEMPT_DIR}"
|
||||
break
|
||||
fi
|
||||
LAST_ATTEMPT_DIR="./target-run/$(echo "${class_name}" | sed 's/[^a-zA-Z0-9._-]/_/g')/attempt-${attempt}/target"
|
||||
sleep 3
|
||||
done
|
||||
|
||||
if [ "${CLASS_OK}" -ne 1 ]; then
|
||||
TEST_RC=1
|
||||
if [ -n "${LAST_ATTEMPT_DIR}" ] && [ -d "${LAST_ATTEMPT_DIR}" ]; then
|
||||
collect_attempt_artifacts "${LAST_ATTEMPT_DIR}"
|
||||
fi
|
||||
fi
|
||||
done < .test-classes.txt
|
||||
|
||||
mkdir -p ./target/mobile-debug
|
||||
docker network inspect mobileci_default > ./target/mobile-debug/network.inspect.json 2>&1 || true
|
||||
for service in android-emulator-1 android-emulator-2; do
|
||||
emu_cid="$(docker ps -q --filter "name=mobileci-${service}" | head -n1 || true)"
|
||||
if [ -n "${emu_cid}" ]; then
|
||||
docker inspect "${emu_cid}" > "./target/mobile-debug/${service}.inspect.json" 2>&1 || true
|
||||
docker logs "${emu_cid}" > "./target/mobile-debug/${service}.log" 2>&1 || true
|
||||
fi
|
||||
done
|
||||
GIT_SHA="$(git -C "$PWD" rev-parse --short HEAD)"
|
||||
mkdir -p ./target/allure-results
|
||||
|
||||
SCREENSHOT_FILES="$(find ./target ./target-run -type f \\( -iname '*.png' -o -iname '*.jpg' -o -iname '*.jpeg' \\) 2>/dev/null || true)"
|
||||
ATTACHMENT_COUNT=0
|
||||
ATTACHMENTS_JSON=""
|
||||
if [ -n "${SCREENSHOT_FILES}" ]; then
|
||||
while IFS= read -r screenshot_file; do
|
||||
if [ -z "${screenshot_file}" ] || [ ! -f "${screenshot_file}" ]; then
|
||||
continue
|
||||
fi
|
||||
ATTACHMENT_COUNT=$((ATTACHMENT_COUNT + 1))
|
||||
ext="$(echo "${screenshot_file}" | awk -F. '{print tolower($NF)}')"
|
||||
if [ "${ext}" = "jpg" ] || [ "${ext}" = "jpeg" ]; then
|
||||
mime="image/jpeg"
|
||||
else
|
||||
ext="png"
|
||||
mime="image/png"
|
||||
fi
|
||||
source_name="external-screenshot-${ATTACHMENT_COUNT}.${ext}"
|
||||
cp "${screenshot_file}" "./target/allure-results/${source_name}" || continue
|
||||
safe_name="$(basename "${screenshot_file}" | sed 's/"/\\"/g')"
|
||||
if [ -n "${ATTACHMENTS_JSON}" ]; then
|
||||
ATTACHMENTS_JSON="${ATTACHMENTS_JSON},"
|
||||
fi
|
||||
ATTACHMENTS_JSON="${ATTACHMENTS_JSON}{\"name\":\"${safe_name}\",\"type\":\"${mime}\",\"source\":\"${source_name}\"}"
|
||||
done <<EOF
|
||||
${SCREENSHOT_FILES}
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ "${ATTACHMENT_COUNT}" -gt 0 ]; then
|
||||
EXTRA_UUID="$(cat /proc/sys/kernel/random/uuid)"
|
||||
TS_MS="$(( $(date +%s) * 1000 ))"
|
||||
cat > "./target/allure-results/${EXTRA_UUID}-result.json" <<EOF
|
||||
{
|
||||
"uuid": "${EXTRA_UUID}",
|
||||
"historyId": "external-screenshots-${BUILD_NUMBER}",
|
||||
"name": "Collected screenshots",
|
||||
"fullName": "pipeline.CollectedScreenshots",
|
||||
"status": "passed",
|
||||
"stage": "finished",
|
||||
"start": ${TS_MS},
|
||||
"stop": ${TS_MS},
|
||||
"labels": [
|
||||
{"name": "suite", "value": "Pipeline Artifacts"},
|
||||
{"name": "package", "value": "pipeline"},
|
||||
{"name": "testClass", "value": "CollectedScreenshots"},
|
||||
{"name": "testMethod", "value": "attach"},
|
||||
{"name": "framework", "value": "jenkins-pipeline"}
|
||||
],
|
||||
"attachments": [${ATTACHMENTS_JSON}],
|
||||
"steps": [],
|
||||
"parameters": []
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
{
|
||||
echo "job=${JOB_NAME}"
|
||||
echo "build=${BUILD_NUMBER}"
|
||||
echo "trigger.user=${RUN_TRIGGER_USER}"
|
||||
echo "trigger.name=${RUN_TRIGGER_NAME}"
|
||||
echo "repo.url=${MOBILE_REPO_URL}"
|
||||
echo "repo.ref=${MOBILE_REPO_REF}"
|
||||
echo "repo.sha=${GIT_SHA}"
|
||||
echo "app.url=${APP_URL}"
|
||||
echo "db.url=${DB_URL}"
|
||||
echo "db.user=${DB_USER}"
|
||||
echo "reservation.owner=${RESERVATION_OWNER}"
|
||||
echo "mobile.emulators=${MOBILE_EMULATORS_VALUE}"
|
||||
echo "mobile.max.emulators=${MOBILE_MAX_EMULATORS:-1}"
|
||||
echo "junit.parallelism=${JUNIT_PARALLELISM:-1}"
|
||||
echo "test.classes.order=${TEST_CLASSES_ORDER}"
|
||||
echo "surefire.rerunFailing=${SUREFIRE_RERUN_FAILING:-1}"
|
||||
} > ./target/allure-results/environment.properties
|
||||
cat > ./target/allure-results/executor.json <<EOF
|
||||
{
|
||||
"name": "Jenkins",
|
||||
"type": "jenkins",
|
||||
"url": "${JENKINS_URL}",
|
||||
"buildName": "${JOB_NAME} #${BUILD_NUMBER}",
|
||||
"buildUrl": "${BUILD_URL}",
|
||||
"reportUrl": "${BUILD_URL}allure",
|
||||
"buildOrder": ${BUILD_NUMBER}
|
||||
}
|
||||
EOF
|
||||
cat > ./target/allure-results/categories.json <<'EOF'
|
||||
[
|
||||
{
|
||||
"name": "Infrastructure issues",
|
||||
"matchedStatuses": ["broken"],
|
||||
"messageRegex": ".*(Connection refused|No route to host|timed out|timeout|No healthy emulators available).*"
|
||||
},
|
||||
{
|
||||
"name": "Mobile UI locator/assertion issues",
|
||||
"matchedStatuses": ["failed", "broken"],
|
||||
"messageRegex": ".*(Element not found|NoSuchElement|AssertionError).*"
|
||||
}
|
||||
]
|
||||
EOF
|
||||
exit "${TEST_RC}"
|
||||
'''
|
||||
}
|
||||
@@ -121,7 +410,8 @@ pipeline {
|
||||
dir('project') {
|
||||
sh '''
|
||||
set +e
|
||||
COMPOSE_FILE="/workspace/otus-autotests/hw8/config/compose/mobile-ci.compose.yml"
|
||||
HW8_ROOT_PATH="${HW8_ROOT:-/workspace/hw8}"
|
||||
COMPOSE_FILE="${HW8_ROOT_PATH}/config/compose/mobile-ci.compose.yml"
|
||||
if docker compose version >/dev/null 2>&1; then
|
||||
compose_cmd() { PROJECT_DIR="$PWD" docker compose -f "${COMPOSE_FILE}" "$@"; }
|
||||
elif docker-compose version >/dev/null 2>&1; then
|
||||
@@ -142,7 +432,7 @@ pipeline {
|
||||
}
|
||||
}
|
||||
junit allowEmptyResults: true, testResults: 'project/target/surefire-reports/*.xml'
|
||||
archiveArtifacts allowEmptyArchive: true, artifacts: 'project/target/**'
|
||||
archiveArtifacts allowEmptyArchive: true, artifacts: 'project/run-info.txt,project/target/**'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,29 +5,48 @@ pipeline {
|
||||
ansiColor('xterm')
|
||||
}
|
||||
stages {
|
||||
stage('Prepare Metadata') {
|
||||
steps {
|
||||
script {
|
||||
wrap([$class: 'BuildUser']) {
|
||||
env.RUN_TRIGGER_USER = env.BUILD_USER_ID ?: env.BUILD_USER ?: 'system'
|
||||
env.RUN_TRIGGER_NAME = env.BUILD_USER ?: env.BUILD_USER_ID ?: 'system'
|
||||
}
|
||||
currentBuild.displayName = "#${env.BUILD_NUMBER} runner"
|
||||
currentBuild.description = "by=${env.RUN_TRIGGER_NAME}; qaRef=${params.QA_REPO_REF}; mobileRef=${params.MOBILE_REPO_REF}"
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Run Jobs In Parallel') {
|
||||
steps {
|
||||
script {
|
||||
def fanout = [:]
|
||||
|
||||
fanout['selenium'] = {
|
||||
build job: 'qa-selenium-tests',
|
||||
def run = build job: 'qa-selenium-tests',
|
||||
wait: true,
|
||||
propagate: true,
|
||||
propagate: false,
|
||||
parameters: [
|
||||
string(name: 'QA_REPO_URL', value: params.QA_REPO_URL),
|
||||
string(name: 'QA_REPO_REF', value: params.QA_REPO_REF),
|
||||
string(name: 'BROWSER', value: params.BROWSER),
|
||||
string(name: 'BASE_URL', value: params.BASE_URL),
|
||||
string(name: 'EXECUTION_MODE', value: params.EXECUTION_MODE),
|
||||
string(name: 'SELENOID_URL', value: params.SELENOID_URL),
|
||||
string(name: 'HEADLESS', value: params.HEADLESS)
|
||||
]
|
||||
writeFile file: 'downstream-selenium.txt', text: "${run.number}|${run.result}\n"
|
||||
}
|
||||
|
||||
fanout['mobile'] = {
|
||||
build job: 'qa-mobile-appium-tests',
|
||||
def run = build job: 'qa-mobile-appium-tests',
|
||||
wait: true,
|
||||
propagate: true,
|
||||
propagate: false,
|
||||
parameters: [
|
||||
string(name: 'MOBILE_REPO_URL', value: params.MOBILE_REPO_URL),
|
||||
string(name: 'MOBILE_REPO_REF', value: params.MOBILE_REPO_REF),
|
||||
string(name: 'MOBILE_MAX_EMULATORS', value: params.MOBILE_MAX_EMULATORS),
|
||||
string(name: 'JUNIT_PARALLELISM', value: params.JUNIT_PARALLELISM),
|
||||
string(name: 'APP_URL', value: params.APP_URL),
|
||||
string(name: 'DB_URL', value: params.DB_URL),
|
||||
string(name: 'DB_USER', value: params.DB_USER),
|
||||
@@ -40,13 +59,64 @@ pipeline {
|
||||
string(name: 'RESERVATION_PASSWORD', value: params.RESERVATION_PASSWORD),
|
||||
string(name: 'RESERVATION_OWNER', value: params.RESERVATION_OWNER)
|
||||
]
|
||||
writeFile file: 'downstream-mobile.txt', text: "${run.number}|${run.result}\n"
|
||||
}
|
||||
|
||||
fanout['api'] = {
|
||||
build job: 'qa-api-citrus-tests', wait: true, propagate: true
|
||||
def run = build job: 'qa-api-citrus-tests',
|
||||
wait: true,
|
||||
propagate: false,
|
||||
parameters: [
|
||||
string(name: 'QA_REPO_URL', value: params.QA_REPO_URL),
|
||||
string(name: 'QA_REPO_REF', value: params.QA_REPO_REF)
|
||||
]
|
||||
writeFile file: 'downstream-api.txt', text: "${run.number}|${run.result}\n"
|
||||
}
|
||||
|
||||
parallel fanout
|
||||
|
||||
def parseRun = { String fileName ->
|
||||
if (!fileExists(fileName)) {
|
||||
return [number: 'n/a', result: 'NOT_BUILT']
|
||||
}
|
||||
def parts = readFile(fileName).trim().tokenize('|')
|
||||
return [
|
||||
number: parts ? parts[0] : 'n/a',
|
||||
result: parts.size() > 1 ? parts[1] : 'UNKNOWN'
|
||||
]
|
||||
}
|
||||
|
||||
def seleniumRun = parseRun('downstream-selenium.txt')
|
||||
def mobileRun = parseRun('downstream-mobile.txt')
|
||||
def apiRun = parseRun('downstream-api.txt')
|
||||
def lines = []
|
||||
lines << "job=${env.JOB_NAME}"
|
||||
lines << "build=${env.BUILD_NUMBER}"
|
||||
lines << "trigger_user=${env.RUN_TRIGGER_USER}"
|
||||
lines << "trigger_name=${env.RUN_TRIGGER_NAME}"
|
||||
lines << "qa_repo_url=${params.QA_REPO_URL}"
|
||||
lines << "qa_repo_ref=${params.QA_REPO_REF}"
|
||||
lines << "mobile_repo_url=${params.MOBILE_REPO_URL}"
|
||||
lines << "mobile_repo_ref=${params.MOBILE_REPO_REF}"
|
||||
lines << "selenium_build=${seleniumRun.number}"
|
||||
lines << "selenium_result=${seleniumRun.result}"
|
||||
lines << "mobile_build=${mobileRun.number}"
|
||||
lines << "mobile_result=${mobileRun.result}"
|
||||
lines << "api_build=${apiRun.number}"
|
||||
lines << "api_result=${apiRun.result}"
|
||||
lines << "selenium_link=/job/qa-selenium-tests/${seleniumRun.number}/"
|
||||
lines << "mobile_link=/job/qa-mobile-appium-tests/${mobileRun.number}/"
|
||||
lines << "api_link=/job/qa-api-citrus-tests/${apiRun.number}/"
|
||||
lines << "selenium_link_abs=${env.JENKINS_URL}job/qa-selenium-tests/${seleniumRun.number}/"
|
||||
lines << "mobile_link_abs=${env.JENKINS_URL}job/qa-mobile-appium-tests/${mobileRun.number}/"
|
||||
lines << "api_link_abs=${env.JENKINS_URL}job/qa-api-citrus-tests/${apiRun.number}/"
|
||||
writeFile file: 'runner-summary.txt', text: lines.join('\n') + '\n'
|
||||
archiveArtifacts allowEmptyArchive: false, artifacts: 'runner-summary.txt'
|
||||
|
||||
def failed = [seleniumRun, mobileRun, apiRun].any { it.result != 'SUCCESS' }
|
||||
if (failed) {
|
||||
error("One or more downstream QA jobs failed. See runner-summary.txt for build links and statuses.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,12 +5,60 @@ pipeline {
|
||||
ansiColor('xterm')
|
||||
}
|
||||
stages {
|
||||
stage('Prepare Metadata') {
|
||||
steps {
|
||||
script {
|
||||
wrap([$class: 'BuildUser']) {
|
||||
env.RUN_TRIGGER_USER = env.BUILD_USER_ID ?: env.BUILD_USER ?: 'system'
|
||||
env.RUN_TRIGGER_NAME = env.BUILD_USER ?: env.BUILD_USER_ID ?: 'system'
|
||||
}
|
||||
currentBuild.displayName = "#${env.BUILD_NUMBER} ${params.BROWSER}/${params.HEADLESS}"
|
||||
currentBuild.description =
|
||||
"by=${env.RUN_TRIGGER_NAME}; repo=${params.QA_REPO_URL}; ref=${params.QA_REPO_REF}; mode=${params.EXECUTION_MODE}"
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Run Selenium Tests In Docker') {
|
||||
steps {
|
||||
sh '''
|
||||
set -eux
|
||||
rm -rf ./sources
|
||||
git clone "${QA_REPO_URL}" ./sources
|
||||
git -C ./sources checkout "${QA_REPO_REF}"
|
||||
GIT_SHA="$(git -C ./sources rev-parse --short HEAD)"
|
||||
if ! grep -q "<artifactId>allure-junit5</artifactId>" ./sources/pom.xml; then
|
||||
awk -v ver="${ALLURE_ADAPTER_VERSION}" '
|
||||
index($0, "</dependencies>") && !done {
|
||||
print " <dependency>"
|
||||
print " <groupId>io.qameta.allure</groupId>"
|
||||
print " <artifactId>allure-junit5</artifactId>"
|
||||
print " <version>" ver "</version>"
|
||||
print " <scope>test</scope>"
|
||||
print " </dependency>"
|
||||
done=1
|
||||
}
|
||||
{ print }
|
||||
' ./sources/pom.xml > ./sources/pom.xml.tmp
|
||||
mv ./sources/pom.xml.tmp ./sources/pom.xml
|
||||
fi
|
||||
|
||||
rm -rf ./artifacts
|
||||
mkdir -p ./artifacts
|
||||
{
|
||||
echo "job=${JOB_NAME}"
|
||||
echo "build=${BUILD_NUMBER}"
|
||||
echo "trigger_user=${RUN_TRIGGER_USER}"
|
||||
echo "trigger_name=${RUN_TRIGGER_NAME}"
|
||||
echo "qa_repo_url=${QA_REPO_URL}"
|
||||
echo "qa_repo_ref=${QA_REPO_REF}"
|
||||
echo "qa_repo_sha=${GIT_SHA}"
|
||||
echo "browser=${BROWSER}"
|
||||
echo "headless=${HEADLESS}"
|
||||
echo "execution_mode=${EXECUTION_MODE}"
|
||||
echo "selenoid_url=${SELENOID_URL}"
|
||||
echo "base_url=${BASE_URL}"
|
||||
echo "timestamp_utc=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||
} > ./artifacts/run-info.txt
|
||||
|
||||
EXTRA_ARGS=""
|
||||
if [ "${BROWSER}" = "chrome" ]; then
|
||||
@@ -20,16 +68,55 @@ pipeline {
|
||||
CID="$(docker create \
|
||||
--add-host=host.docker.internal:host-gateway \
|
||||
localhost:5005/otus/test-selenium:1.0.0 \
|
||||
bash -lc "set -e; cd /workspace; mvn -Dexecution.mode=${EXECUTION_MODE} -Dbrowser=${BROWSER} -Dbrowser.version= -Dselenoid.url=${SELENOID_URL} -Dbase.url=${BASE_URL} -Dselenide.headless=${HEADLESS} -Dallure.results.directory=target/allure-results ${EXTRA_ARGS} test")"
|
||||
bash -lc "set -e; cd /workspace; mvn -Dallure.version=${ALLURE_ADAPTER_VERSION} -Dexecution.mode=${EXECUTION_MODE} -Dbrowser=${BROWSER} -Dbrowser.version= -Dselenoid.url=${SELENOID_URL} -Dbase.url=${BASE_URL} -Dselenide.headless=${HEADLESS} -Dallure.results.directory=target/allure-results ${EXTRA_ARGS} test")"
|
||||
cleanup_container() {
|
||||
docker rm -f "${CID}" >/dev/null 2>&1 || true
|
||||
}
|
||||
trap cleanup_container EXIT INT TERM
|
||||
tar -C /workspace/otus-autotests/homework_4 -cf - . | docker cp - "${CID}:/workspace"
|
||||
tar -C ./sources -cf - . | docker cp - "${CID}:/workspace"
|
||||
set +e
|
||||
docker start -a "${CID}"
|
||||
TEST_RC=$?
|
||||
docker cp "${CID}:/workspace/target" "./artifacts/target" || true
|
||||
docker cp "${CID}:/workspace/target" "./artifacts" || true
|
||||
mkdir -p ./artifacts/target/allure-results
|
||||
{
|
||||
echo "job=${JOB_NAME}"
|
||||
echo "build=${BUILD_NUMBER}"
|
||||
echo "trigger.user=${RUN_TRIGGER_USER}"
|
||||
echo "trigger.name=${RUN_TRIGGER_NAME}"
|
||||
echo "repo.url=${QA_REPO_URL}"
|
||||
echo "repo.ref=${QA_REPO_REF}"
|
||||
echo "repo.sha=${GIT_SHA}"
|
||||
echo "browser=${BROWSER}"
|
||||
echo "headless=${HEADLESS}"
|
||||
echo "execution.mode=${EXECUTION_MODE}"
|
||||
echo "base.url=${BASE_URL}"
|
||||
} > ./artifacts/target/allure-results/environment.properties
|
||||
cat > ./artifacts/target/allure-results/executor.json <<EOF
|
||||
{
|
||||
"name": "Jenkins",
|
||||
"type": "jenkins",
|
||||
"url": "${JENKINS_URL}",
|
||||
"buildName": "${JOB_NAME} #${BUILD_NUMBER}",
|
||||
"buildUrl": "${BUILD_URL}",
|
||||
"reportUrl": "${BUILD_URL}allure",
|
||||
"buildOrder": ${BUILD_NUMBER}
|
||||
}
|
||||
EOF
|
||||
cat > ./artifacts/target/allure-results/categories.json <<'EOF'
|
||||
[
|
||||
{
|
||||
"name": "Infrastructure issues",
|
||||
"matchedStatuses": ["broken"],
|
||||
"messageRegex": ".*(Connection refused|No route to host|timed out|timeout).*"
|
||||
},
|
||||
{
|
||||
"name": "UI locator/assertion issues",
|
||||
"matchedStatuses": ["failed", "broken"],
|
||||
"messageRegex": ".*(Element not found|NoSuchElement|AssertionError).*"
|
||||
}
|
||||
]
|
||||
EOF
|
||||
trap - EXIT INT TERM
|
||||
docker rm -f "${CID}" || true
|
||||
exit "${TEST_RC}"
|
||||
@@ -47,7 +134,7 @@ pipeline {
|
||||
}
|
||||
}
|
||||
junit allowEmptyResults: true, testResults: 'artifacts/target/surefire-reports/*.xml'
|
||||
archiveArtifacts allowEmptyArchive: true, artifacts: 'artifacts/target/**'
|
||||
archiveArtifacts allowEmptyArchive: true, artifacts: 'artifacts/run-info.txt,artifacts/target/**'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,6 @@
|
||||
parameters:
|
||||
- string:
|
||||
name: JJB_PATH
|
||||
default: /workspace/otus-autotests/hw8/config/jobs
|
||||
default: /workspace/hw8/config/jobs
|
||||
description: "Путь до JJB-конфигов"
|
||||
dsl: !include-raw-verbatim: ../scripts/jobs-uploader.groovy
|
||||
|
||||
@@ -8,4 +8,13 @@
|
||||
properties:
|
||||
- build-discarder:
|
||||
num-to-keep: 50
|
||||
parameters:
|
||||
- string:
|
||||
name: QA_REPO_URL
|
||||
default: https://git.kovbasa.ru/otus-autotests/homework_4.git
|
||||
description: "Git URL репозитория с Selenium/API тестами"
|
||||
- string:
|
||||
name: QA_REPO_REF
|
||||
default: master
|
||||
description: "Git branch/tag/commit для checkout"
|
||||
dsl: !include-raw-verbatim: ../scripts/qa-api-citrus-tests.groovy
|
||||
|
||||
@@ -9,6 +9,38 @@
|
||||
- build-discarder:
|
||||
num-to-keep: 30
|
||||
parameters:
|
||||
- string:
|
||||
name: MOBILE_REPO_URL
|
||||
default: https://git.kovbasa.ru/otus-autotests/homework_7.git
|
||||
description: "Git URL репозитория с Appium тестами"
|
||||
- string:
|
||||
name: MOBILE_REPO_REF
|
||||
default: master
|
||||
description: "Git branch/tag/commit для checkout"
|
||||
- string:
|
||||
name: ALLURE_ADAPTER_VERSION
|
||||
default: 2.29.1
|
||||
description: "Версия allure-junit5 адаптера"
|
||||
- choice:
|
||||
name: MOBILE_MAX_EMULATORS
|
||||
choices:
|
||||
- "1"
|
||||
- "2"
|
||||
description: "Сколько эмуляторов использовать в прогоне (1=стабильнее, 2=быстрее)"
|
||||
- choice:
|
||||
name: JUNIT_PARALLELISM
|
||||
choices:
|
||||
- "1"
|
||||
- "2"
|
||||
description: "Параллельность JUnit классов в мобильных тестах"
|
||||
- string:
|
||||
name: TEST_CLASSES_ORDER
|
||||
default: "ru.otus.mobile.tests.WishlistsTest,ru.otus.mobile.tests.GiftsTest,ru.otus.mobile.tests.ReservationTest"
|
||||
description: "Порядок классов для поочередного запуска (-Dtest)"
|
||||
- string:
|
||||
name: SUREFIRE_RERUN_FAILING
|
||||
default: "0"
|
||||
description: "Количество surefire rerun внутри одного запуска класса (обычно 0, т.к. ретрай делается на уровне pipeline)"
|
||||
- string:
|
||||
name: APP_URL
|
||||
default: http://wiremock:8080/wishlist.apk
|
||||
|
||||
@@ -9,6 +9,28 @@
|
||||
- build-discarder:
|
||||
num-to-keep: 50
|
||||
parameters:
|
||||
- string:
|
||||
name: QA_REPO_URL
|
||||
default: https://git.kovbasa.ru/otus-autotests/homework_4.git
|
||||
- string:
|
||||
name: QA_REPO_REF
|
||||
default: master
|
||||
- string:
|
||||
name: MOBILE_REPO_URL
|
||||
default: https://git.kovbasa.ru/otus-autotests/homework_7.git
|
||||
- string:
|
||||
name: MOBILE_REPO_REF
|
||||
default: master
|
||||
- choice:
|
||||
name: MOBILE_MAX_EMULATORS
|
||||
choices:
|
||||
- "1"
|
||||
- "2"
|
||||
- choice:
|
||||
name: JUNIT_PARALLELISM
|
||||
choices:
|
||||
- "1"
|
||||
- "2"
|
||||
- choice:
|
||||
name: BROWSER
|
||||
choices:
|
||||
@@ -19,7 +41,7 @@
|
||||
default: https://otus.ru
|
||||
- string:
|
||||
name: EXECUTION_MODE
|
||||
default: selenoid
|
||||
default: local
|
||||
- string:
|
||||
name: SELENOID_URL
|
||||
default: http://host.docker.internal:4444/wd/hub
|
||||
|
||||
@@ -9,6 +9,18 @@
|
||||
- build-discarder:
|
||||
num-to-keep: 50
|
||||
parameters:
|
||||
- string:
|
||||
name: QA_REPO_URL
|
||||
default: https://git.kovbasa.ru/otus-autotests/homework_4.git
|
||||
description: "Git URL репозитория с Selenium/API тестами"
|
||||
- string:
|
||||
name: QA_REPO_REF
|
||||
default: master
|
||||
description: "Git branch/tag/commit для checkout"
|
||||
- string:
|
||||
name: ALLURE_ADAPTER_VERSION
|
||||
default: 2.29.1
|
||||
description: "Версия allure-junit5 адаптера"
|
||||
- choice:
|
||||
name: BROWSER
|
||||
choices:
|
||||
@@ -21,7 +33,7 @@
|
||||
description: "Базовый URL тестируемого сайта"
|
||||
- string:
|
||||
name: EXECUTION_MODE
|
||||
default: selenoid
|
||||
default: local
|
||||
description: "Режим запуска (local|selenoid)"
|
||||
- string:
|
||||
name: SELENOID_URL
|
||||
|
||||
+18
-2
@@ -18,13 +18,29 @@
|
||||
- build-button
|
||||
|
||||
- view:
|
||||
name: QA
|
||||
name: QA-Runner
|
||||
view-type: list
|
||||
description: "Тестовые job и раннер"
|
||||
description: "Точка входа для запуска всех тестов"
|
||||
filter-executors: true
|
||||
filter-queue: true
|
||||
job-name:
|
||||
- qa-runner
|
||||
columns:
|
||||
- status
|
||||
- weather
|
||||
- job
|
||||
- last-success
|
||||
- last-failure
|
||||
- last-duration
|
||||
- build-button
|
||||
|
||||
- view:
|
||||
name: QA-Tests
|
||||
view-type: list
|
||||
description: "Тестовые job"
|
||||
filter-executors: true
|
||||
filter-queue: true
|
||||
job-name:
|
||||
- qa-selenium-tests
|
||||
- qa-api-citrus-tests
|
||||
- qa-mobile-appium-tests
|
||||
|
||||
Reference in New Issue
Block a user