diff --git a/.github/workflows/1_helloworld.yml b/.github/workflows/1_helloworld.yml
new file mode 100644
index 0000000..9e9fda2
--- /dev/null
+++ b/.github/workflows/1_helloworld.yml
@@ -0,0 +1,31 @@
+name: "1. Согласована и сформулирована тема курсовой"
+
+on:
+ push:
+ branches:
+ - main
+
+jobs:
+ check_hello_world_dir_not_empty:
+ name: "Проверка наличия каталога ./hello_world/"
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ name: Check out current commit
+
+ - name: check
+ run: |
+ dir="./hello_world/"
+ if [ -d "${dir}" ]; then
+ if [ "$(ls -A ${dir})" ]; then
+ echo "::notice::Предварительная проверка пройдена - каталог ${dir} создан и не пуст"
+ exit 0
+ else
+ echo "::error::Предварительная проверка не пройдена - каталог ${dir} пуст"
+ exit 1
+ fi
+
+ else
+ echo "::error::Предварительная проверка не пройдена - каталог не найден ${dir}"
+ exit 1
+ fi
diff --git a/.github/workflows/2_usecase.yml b/.github/workflows/2_usecase.yml
new file mode 100644
index 0000000..b7d2deb
--- /dev/null
+++ b/.github/workflows/2_usecase.yml
@@ -0,0 +1,65 @@
+name: "2. Usecase"
+
+on:
+ push:
+ branches:
+ - main
+ gollum:
+
+jobs:
+ check_mockup_uc_wiki:
+ name: "Проверка наличия вики-страницы \"Макет и сценарий использования\" и разделов \"Макет UI\" \"Сценарий использования\" в ней"
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ name: Check wiki
+ with:
+ repository: ${{github.repository}}.wiki
+ - name: check
+ run: |
+ page="Макет-и-сценарий-использования.md"
+ mockup_header="Макет UI"
+ uc_header="Сценарий использования"
+
+ if ! [[ -f "${page}" ]]; then
+ echo "::error::Предварительная проверка не пройдена - не найдена вики-страница \"Макет и сценарий использования\""
+ exit 1
+ fi
+
+ if ! cat "${page}" | grep -q "${mockup_header}"; then
+ echo "::error::Предварительная проверка не пройдена - не найден заголовок ${mockup_header}"
+ exit 1
+ fi
+
+
+ if ! cat "${page}" | grep -q "${uc_header}"; then
+ echo "::error::Предварительная проверка не пройдена - не найден заголовок ${uc_header}"
+ exit 1
+ fi
+
+ if ! cat "${page}" | grep -iq "импорт"; then
+ echo "::error::Предварительная проверка не пройдена - не найден сценарий, связанный с импортом данных в систему"
+ exit 1
+ fi
+
+ if ! cat "${page}" | grep -iq "экспорт"; then
+ echo "::error::Предварительная проверка не пройдена - не найден сценарий, связанный с экспортом данных в систему"
+ exit 1
+ fi
+
+ if ! cat "${page}" | grep -iq "статистик"; then
+ echo "::error::Предварительная проверка не пройдена - не найден сценарий, связанный с подсчетом статистики в системе"
+ exit 1
+ fi
+
+ if ! cat "${page}" | grep -iq '](https\:\/\/github.com\/moevm\/[^/]\+\/assets[^\)]\+)'; then
+ echo "::error::Предварительная проверка не пройдена - не найдены изображения макета из репозитория. Вставьте их через \![Название картинки](полная ссылка вида https://github.com/moevm/ВАШ РЕПО/assets/34864759/8f850ef1-fc3d-4adb-a7aa-81598cc7794c) . Если вы храните изображение макета где-то ВНЕ репозитория, то, пожалуйста, разместите файлы в репо - иначе потом очень сложно собирать материалы вашей проекта."
+ exit 1
+ fi
+
+ if cat "${page}" | grep 'https\:\/\/' | grep -qv github; then
+ echo "::error::Предварительная проверка не пройдена - найдены ссылки на сторонние сервисы. Если части вашего макета и сценария размещены где-то еще, то, пожалуйста 1) соберите их на вики 2) если у вас сложный макет с figma и тд - положите в репо качественную схему в виде графа. Иначе потом очень сложно собирать материалы вашего проекта."
+ exit 1
+ fi
+
+ echo "::notice::Предварительная проверка пройдена - вики-страница найдена, нужные заголовки присутствуют"
diff --git a/.github/workflows/3_data_model.yml b/.github/workflows/3_data_model.yml
new file mode 100644
index 0000000..1538cdb
--- /dev/null
+++ b/.github/workflows/3_data_model.yml
@@ -0,0 +1,78 @@
+name: "3. Модель данных"
+
+on:
+ push:
+ branches:
+ - main
+ gollum:
+
+jobs:
+ check_data_model:
+ name: "Проверка наличия вики-страницы \"Модель данных\" и разделов \"Нереляционная модель\", \"Реляционная модель\", \"Сравнение моделей\", \"Вывод\" в ней"
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ name: Check wiki
+ with:
+ repository: ${{github.repository}}.wiki
+ - name: check
+ run: |
+ page="Модель-данных.md"
+ nosql_model="Нереляционная модель"
+ sql_model="Реляционная модель"
+ comparison="Сравнение моделей"
+ conclusion="Вывод"
+ query_examples="Примеры запросов"
+ data_examples="Примеры данных"
+ redundancy="Избыточность данных"
+
+ if ! [[ -f "${page}" ]]; then
+ echo "::error::Предварительная проверка не пройдена - не найдена вики-страница \"Модель данных\""
+ exit 1
+ fi
+
+ if ! cat "${page}" | grep -q "${nosql_model}"; then
+ echo "::error::Предварительная проверка не пройдена - не найден заголовок ${nosql_model}"
+ exit 1
+ fi
+
+
+ if ! cat "${page}" | grep -q "${sql_model}"; then
+ echo "::error::Предварительная проверка не пройдена - не найден заголовок ${sql_model}"
+ exit 1
+ fi
+
+ image_count=`cat "${page}" | grep '](https\:\/\/github.com\/moevm\/[^/]\+\/assets[^\)]\+)' | wc -l`
+ if [[ ${image_count} -lt 2 ]]; then
+ echo "::error::Предварительная проверка не пройдена - не найдены изображения для схем моделей данных. Для реляционной и нереляционной модели необходимо разместить изображения схем моделей данных. Вставьте их через \![Название картинки](полная ссылка вида https://github.com/moevm/ВАШ РЕПО/assets/34864759/8f850ef1-fc3d-4adb-a7aa-81598cc7794c) . Если вы храните изображение макета где-то ВНЕ репозитория, то, пожалуйста, разместите файлы в репо - иначе потом очень сложно собирать материалы вашей проекта. "
+ exit 1
+ fi
+
+ query_examples_count=`cat "${page}" | grep "${query_examples}" | wc -l`
+ if [[ "${query_examples_count}" != "2" ]]; then
+ echo "::error::Предварительная проверка не пройдена - не найдены заголовоки ${query_examples} (соответствующие подразделы должны быть в разделах с нереляционной и реляционной моделями)."
+ exit 1
+ fi
+
+ data_examples_count=`cat "${page}" | grep "${data_examples}" | wc -l`
+ if [[ "${data_examples_count}" != "2" ]]; then
+ echo "::error::Предварительная проверка не пройдена - не найдены заголовоки ${data_examples} (соответствующие подразделы должны быть в разделах с нереляционной и реляционной моделями)."
+ exit 1
+ fi
+
+ redundancy_count=`cat "${page}" | grep "${redundancy}" | wc -l`
+ if [[ "${redundancy_count}" != "2" ]]; then
+ echo "::error::Предварительная проверка не пройдена - не найдены заголовоки ${redundancy} (соответствующие подразделы должны быть в разделах с нереляционной и реляционной моделями)."
+ exit 1
+ fi
+
+ if ! cat "${page}" | grep -q "${comparison}"; then
+ echo "::error::Предварительная проверка не пройдена - не найден заголовок ${comparison}"
+ exit 1
+ fi
+
+ if ! cat "${page}" | grep -q "${conclusion}"; then
+ echo "::error::Предварительная проверка не пройдена - не найден заголовок ${conclusion}"
+ exit 1
+ fi
+ echo "::notice::Предварительная проверка пройдена - вики-страница найдена, нужные заголовки присутствуют "
diff --git a/.github/workflows/4_prototype_store_and_view.yml b/.github/workflows/4_prototype_store_and_view.yml
new file mode 100644
index 0000000..5f167ef
--- /dev/null
+++ b/.github/workflows/4_prototype_store_and_view.yml
@@ -0,0 +1,26 @@
+name: "4. Прототип хранение и представление"
+
+on:
+ push:
+ branches:
+ - main
+
+jobs:
+ check_prototype_store_and_view:
+ name: "Проверка наличия тега 0.5"
+ runs-on: ubuntu-20.04
+ steps:
+ - uses: actions/checkout@v4
+ name: Check out current commit
+ with:
+ fetch-depth: 0
+
+ - name: check
+ run: |
+ TAG="0.5"
+ if [ $(git tag -l "${TAG}") ]; then
+ echo "::notice::Тег ${TAG} найден"
+ else
+ echo "::error::Тег ${TAG} не найден"
+ exit 1
+ fi
diff --git a/.github/workflows/5_prototype_analysis.yml b/.github/workflows/5_prototype_analysis.yml
new file mode 100644
index 0000000..36c0027
--- /dev/null
+++ b/.github/workflows/5_prototype_analysis.yml
@@ -0,0 +1,174 @@
+name: "5. Прототип анализ"
+
+on:
+ push:
+ branches:
+ - main
+
+jobs:
+ check_tag_08_docker_compose:
+ name: "Проверка наличия тега 0.8 и работоспособности docker-compose"
+ runs-on: ubuntu-20.04
+ steps:
+ - uses: actions/checkout@v4
+ name: Check out current commit
+ with:
+ fetch-depth: 0
+
+ - name: There are at least one Dockerfile
+ run: |
+ if ! find ./ | grep -q 'Dockerfile$'
+ then
+ echo "::error:: Не найдены файлы с названием Dockerfile."
+ exit 1
+ fi
+
+ - name: Lint Dockerfile
+ uses: hadolint/hadolint-action@v3.1.0
+ with:
+ dockerfile: Dockerfile
+ recursive: true
+ failure-threshold: error
+ override-error: DL3006, DL3000, DL3007, DL3008, DL3009, DL3013, DL3016, DL3018, DL3020, DL3028, DL3037, DL3047, DL4001, DL4003, DL4004
+
+ - name: Check docker-compose.yml
+ run: |
+ set -e
+
+ dc_file=${1:-"./docker-compose.yml"}
+
+ services_count=`yq '.services | length' ${dc_file}`
+ if [[ "${services_count}" < "2" ]];
+ then
+ echo "::error:: Ошибка - слишком мало сервисов в конфигурации. У вас должно быть минимум два сервиса - приложение и СУБД."
+ exit 1
+ fi
+
+ db_service=`yq '.services.db' ${dc_file}`
+ if [[ "${db_service}" == "null" ]];
+ then
+ echo "::error:: Ошибка - нет явно заданного сервиса для СУБД (с названием db)"
+ exit 1
+ fi
+
+ if [[ "`yq '.services.db.ports' ${dc_file}`" != "null" ]];
+ then
+ echo "::error:: Ошибка - в сервисе db открыты сетевые порты через ports. Для работы приложения они не нужны, если вам требуется доступ для СУБД в отладочных целях, то можно или поднять веб-интерфейс (и ему открыть порты), или получать доступ по внутренней сети докера. "
+ exit 1
+ fi
+
+ if [[ "`yq '.services.db.volumes' ${dc_file}`" == "null" ]];
+ then
+ echo "::error:: Ошибка - в сервисе db не организованы volumes. По заданию они требуются для того, чтобы сохранять данные БД между запусками вашей конфигурации"
+ exit 1
+ fi
+
+ if yq '.services.db.volumes' ${dc_file} | grep -q '^[^/a-zA-Z]*/'
+ then
+ echo "::error:: Ошибка - в сервисе db volumes использует монтирование каталогов. Используйте вместо этого именно volumes ( https://docs.docker.com/storage/volumes/#use-a-volume-with-docker-compose) - это гораздо удобнее и позволяет управлять таким хранилищем через докер."
+ exit 1
+ fi
+
+ if yq '.network' ${dc_file} | grep -q 'host' ;
+ then
+ echo "::error:: Ошибка - сеть типа host. Пожалуйста, не используйте данный тип сети: он максимально небезопасен (так как неглядя мапит все порты вашей конфигурации на адаптер хоста) и неудобен. Укажите вместо этого конкретные маппинги портов в соответствующих директивах ports"
+ exit 1
+ fi
+
+ # Проверка volumes
+ echo "::info:: Ниже будут все volumes всех сервисов"
+ yq '.services.*.volumes' ${dc_file}
+ if yq '.services.*.volumes' ${dc_file} | grep -v ':ro$' | grep -q '^[^/a-zA-Z]*/'
+ then
+ echo "::error:: Ошибка - у вас есть смонтированные в volumes файлы и/или каталоги без метки ro (read-only, https://docs.docker.com/compose/compose-file/05-services/#short-syntax-5). Монтируемый каталог или файл нужно или копировать на этапе сборки контейнера (если там данные, которые не предполагают изменение), или ставить опцию :ro ."
+ exit 1
+ fi
+
+
+ # Проверка всех сервисов на общие ошибки
+ for i in $(seq 0 $(( services_count - 1 )) );
+ do
+ service=`yq '.services | keys ['$i']' ${dc_file}`
+ echo "::info:: Проверка сервиса: ${service}"
+ yq '.services.'$service ${dc_file}
+
+ image=`yq '.services.'$service'.image' ${dc_file}`
+ if [[ "${image}" != "null" ]];
+ then
+ if echo ${image} | grep -qE ':latest|^[^:]*$';
+ then
+ echo "::error:: Ошибка - отсутствие тега или использование тега latest. Обе эти ситуации означают, что вы не привязаны к опредлеленной версии образа и в случае его обновления работа приложения может нарушится (а вы об этом узнаете только постфактум). Укажите явно тег."
+ exit 1
+ fi
+ fi
+
+ ports=`yq '.services.'$service'.ports' ${dc_file}`
+ if [[ "${ports}" != "null" ]];
+ then
+ if echo ${ports} | grep -qv '^[^0-9]*127.0.0.1:';
+ then
+ echo "::error:: Ошибка - явно не указан интерфейс при маппинге портов. По умолчанию (если не указывать вот так 127.0.0.1:3000:80), докер мапит на все доступные интерфейсы и это нарушает безопасность. Добавьте 127.0.0.1: к содержимому директивы ports "
+ exit 1
+ fi
+ fi
+
+ external_ports=`echo $ports | grep '127.0.0.1' | sed 's/^[^1]*127.0.0.1:\([^:]*\):[^:]*$/\1/g'`
+ for port in $external_ports;
+ do
+ if [[ "$port" < 1025 ]];
+ then
+ echo "::error:: Ошибка - использование внешних портов хоста <=1024. Данные порты зарезервированы под системные нужды, лучше использовать порты с номерами выше 8000 (чтобы не было коллизий). "
+ exit 1
+ fi
+ done
+
+ done
+
+
+ - name: Build docker-compose
+ run: |
+ docker-compose build --no-cache
+
+ - name: Run docker-compose
+ run: |
+ docker-compose up -d
+ sleep 30
+
+ - name: Check containers are alive
+ run: |
+ echo "::notice:: docker ps --filter status=exited"
+ docker ps --filter status=exited
+ exited_count=`docker ps --filter status=exited | tail -n +2 | wc -l`
+
+ echo "::notice:: docker ps --filter status=dead"
+ docker ps --filter status=dead
+ dead_count=`docker ps --filter status=dead | tail -n +2 | wc -l`
+
+ echo "::notice:: docker ps --filter status=restarting"
+ docker ps --filter status=restarting
+ restarting_count=`docker ps --filter status=restarting | tail -n +2 | wc -l`
+
+ echo "::notice:: docker ps --filter status=paused"
+ docker ps --filter status=paused
+ paused_count=`docker ps --filter status=paused | tail -n +2 | wc -l`
+
+ echo "::notice:: docker ps --filter status=created"
+ docker ps --filter status=created
+ created_count=`docker ps --filter status=created | tail -n +2 | wc -l`
+
+ if [[ "${exited_count}" != "0" ]] || [[ "${restarting_count}" != "0" ]] || [[ "${paused_count}" != "0" ]] || [[ "${created_count}" != "0" ]] || [[ "${created_count}" != "0" ]]; then
+ echo "::error::Часть контейнеров не находится в состоянии running (завершили или не начали свою работу корректно) "
+ exit 1
+ fi
+
+
+
+ - name: check_tag
+ run: |
+ TAG="0.8"
+ if [ $(git tag -l "${TAG}") ]; then
+ echo "::notice::Тег ${TAG} найден"
+ else
+ echo "::error::Тег ${TAG} не найден"
+ exit 1
+ fi
diff --git a/.github/workflows/6_report.yml b/.github/workflows/6_report.yml
new file mode 100644
index 0000000..19de983
--- /dev/null
+++ b/.github/workflows/6_report.yml
@@ -0,0 +1,29 @@
+name: "6. Пояснительная записка"
+
+on:
+ push:
+ branches:
+ - main
+
+jobs:
+ check_reports:
+ name: "Проверка наличия пояснительной записки (report.doc / report.docx / report.odt + report.pdf в корне репо)"
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ name: Check out current commit
+
+ - name: check
+ run: |
+
+ if ! ( [[ -f "./report.docx" ]] || [[ -f "./report.doc" ]] || [[ -f "./report.odt" ]] ) ; then
+ echo "::error::Предварительная проверка не пройдена - не найдены редактируемые версии пояснительной записки"
+ exit 1
+ fi
+
+ if ! [[ -f "./report.pdf" ]] ; then
+ echo "::error::Предварительная проверка не пройдена - не найдена pdf версия записки"
+ exit 1
+ fi
+
+ echo "::notice::Предварительная проверка пройдена - файлы записки найдены"
diff --git a/.github/workflows/7_app_is_ready.yml b/.github/workflows/7_app_is_ready.yml
new file mode 100644
index 0000000..c3f9655
--- /dev/null
+++ b/.github/workflows/7_app_is_ready.yml
@@ -0,0 +1,26 @@
+name: "7. App is ready"
+
+on:
+ push:
+ branches:
+ - main
+
+jobs:
+ check_app_is_ready:
+ name: "Проверка наличия тега 1.0"
+ runs-on: ubuntu-20.04
+ steps:
+ - uses: actions/checkout@v4
+ name: Check out current commit
+ with:
+ fetch-depth: 0
+
+ - name: check
+ run: |
+ TAG="1.0"
+ if [ $(git tag -l "${TAG}") ]; then
+ echo "::notice::Тег ${TAG} найден"
+ else
+ echo "::error::Тег ${TAG} не найден"
+ exit 1
+ fi
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..9e07660
--- /dev/null
+++ b/README.md
@@ -0,0 +1,18 @@
+# nosql_template
+
+
+## Предварительная проверка заданий
+
+![1. Согласована и сформулирована тема курсовой]( ./../../actions/workflows/1_helloworld.yml/badge.svg)
+
+![2. Usecase]( ./../../actions/workflows/2_usecase.yml/badge.svg)
+
+![3. Модель данных]( ./../../actions/workflows/3_data_model.yml/badge.svg)
+
+![4. Прототип хранение и представление]( ./../../actions/workflows/4_prototype_store_and_view.yml/badge.svg)
+
+![5. Прототип анализ]( ./../../actions/workflows/5_prototype_analysis.yml/badge.svg)
+
+![6. Пояснительная записка]( ./../../actions/workflows/6_report.yml/badge.svg)
+
+![7. App is ready]( ./../../actions/workflows/7_app_is_ready.yml/badge.svg)