Initial commit

This commit is contained in:
2026-04-28 22:59:35 +03:00
commit 24aa9bcf82
15 changed files with 477 additions and 0 deletions
View File
+73
View File
@@ -0,0 +1,73 @@
# Operating system files
.DS_Store
Thumbs.db
# Dependency directories
node_modules/
venv/
.env
*.env
# Build and output folders
dist/
build/
out/
coverage/
coverage-final.json
# Logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
*.log
# Temporary files
tmp/
temp/
*.tmp
*.swp
*.swo
# IDE/editor directories
.vscode/
.idea/
*.sublime-workspace
*.sublime-project
# API/Web project specific
.env.local
.env.*.local
/.next/
/.nuxt/
/.vercel/
/.cache/
# Compiled files
*.class
*.dll
*.exe
*.o
*.pyc
*.pyo
*.pyd
__pycache__/
# Misc
.DS_Store
*.bak
*.backup
*.orig
*.rej
# Ignore secrets and credentials
secret*
credentials*
# Generated documentation
doc/api/
docs/
# Docker
docker-compose.override.yml
*.log
+32
View File
@@ -0,0 +1,32 @@
.PHONY: help
dc = docker compose
devDC = $(dc) -f compose.yaml -f compose.dev.yaml
project = dc
help:
@echo "Usage: <command> \n"
@echo "- prod"
@echo "- dev"
@echo "- down"
@echo "- log"
@echo "- config"
@echo "- devConfig"
prod:
$(dc) up -d
dev:
$(devDC) up -d
down:
$(devDC) down
logs:
$(devDC) logs -f --tail=20
config:
$(devDC) config
devConfig:
$(devDC) config
+19
View File
@@ -0,0 +1,19 @@
# ProjectName
ProjectName — это проект для организации задач команды и управления рабочими процессами.
Этот репозиторий `deploy` служит оркестратором проекта.
Он содержит инфраструктуру и конфигурации для развёртывания ProjectName, управления окружениями и запуска служб.
Основные задачи репозитория `deploy`:
- подготовка инфраструктуры для приложения;
- настройка CI/CD и автоматического деплоя;
- управление конфигурациями окружений;
- запуск и мониторинг сервисов.
Использование:
1. Настройте переменные окружения и секреты.
2. Запустите процедуры развёртывания.
3. Следите за состоянием сервиса и логами.
Этот репозиторий не содержит основную логику приложения ProjectName, а отвечает за его развёртывание и эксплуатацию.
+91
View File
@@ -0,0 +1,91 @@
# git-cliff ~ default configuration file
# https://git-cliff.org/docs/configuration
#
# Lines starting with "#" are comments.
# Configuration options are organized into tables and keys.
# See documentation for more information on available options.
[changelog]
# changelog header
header = """
# Changelog\n
All notable changes to this project will be documented in this file.\n
"""
# template for the changelog body
# https://keats.github.io/tera/docs/#introduction
body = """
{% if version %}\
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
{% else %}\
## [unreleased]
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | striptags | trim | upper_first }}
{% for commit in commits %}
- {% if commit.scope %}*({{ commit.scope }})* {% endif %}\
{% if commit.breaking %}[**breaking**] {% endif %}\
{{ commit.message | upper_first }}\
{% endfor %}
{% endfor %}\n
"""
# template for the changelog footer
footer = """
<!-- generated by git-cliff -->
"""
# remove the leading and trailing s
trim = true
# postprocessors
postprocessors = [
{ pattern = '(IDA-\d+)', replace = "[${1}](https://ru.yougile.com/team/a0c003776084/Identity#${1})" }
# { pattern = '<REPO>', replace = "https://github.com/orhun/git-cliff" }, # replace repository URL
]
[git]
# parse the commits based on https://www.conventionalcommits.org
conventional_commits = true
# filter out the commits that are not conventional
filter_unconventional = true
# process each line of a commit as an individual commit
split_commits = false
# regex for preprocessing the commit messages
commit_preprocessors = [
# Replace issue numbers
#{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](<REPO>/issues/${2}))"},
# Check spelling of the commit with https://github.com/crate-ci/typos
# If the spelling is incorrect, it will be automatically fixed.
#{ pattern = '.*', replace_command = 'typos --write-changes -' },
]
# regex for parsing and grouping commits
commit_parsers = [
{ message = "^feat", group = "<!-- 0 -->🚀 Features" },
{ message = "^fix", group = "<!-- 1 -->🐛 Bug Fixes" },
{ message = "^fixes", group = "<!-- 10 -->🐛 Fixes" },
{ message = "^doc", group = "<!-- 3 -->📚 Documentation" },
{ message = "^perf", group = "<!-- 4 -->⚡ Performance" },
{ message = "^refactor", group = "<!-- 2 -->🚜 Refactor" },
{ message = "^style", group = "<!-- 5 -->🎨 Styling" },
{ message = "^test", group = "<!-- 6 -->🧪 Testing" },
{ message = "^chore\\(release\\): prepare for", skip = true },
{ message = "^chore\\(deps.*\\)", skip = true },
{ message = "^chore\\(pr\\)", skip = true },
{ message = "^chore\\(pull\\)", skip = true },
{ message = "^chore|^ci", group = "<!-- 7 -->⚙️ Miscellaneous Tasks" },
{ body = ".*security", group = "<!-- 8 -->🛡️ Security" },
{ message = "^revert", group = "<!-- 9 -->◀️ Revert" },
]
# protect breaking changes from being skipped due to matching a skipping commit_parser
protect_breaking_commits = false
# filter out the commits that are not matched by commit parsers
filter_commits = false
# regex for matching git tags
# tag_pattern = "v[0-9].*"
# regex for skipping tags
# skip_tags = ""
# regex for ignoring tags
# ignore_tags = ""
# sort the tags topologically
topo_order = false
# sort the commits inside sections by oldest/newest order
sort_commits = "oldest"
# limit the number of commits included in the changelog.
# limit_commits = 42
+22
View File
@@ -0,0 +1,22 @@
services:
adminer:
container_name: ${APP_PREFIX}-${APP_ENV}-adminer
image: adminer:${DEPLOY_ADMINER_TAG:-5.4.2-standalone}
restart: always
environment:
ADMINER_PLUGINS: >
tables-filter tinymce dump-json table-structure pretty-json-column
dark-switcher idsmk-edit-foreign
ADMINER_DESIGN: dracula
ADMINER_DEFAULT_SERVER: db
links:
- "db"
depends_on:
db:
condition: service_healthy
volumes:
- ./services/adminer/idsmk-edit-foreign.php:/var/www/html/plugins/idsmk-edit-foreign.php:ro
- /etc/localtime:/etc/localtime:ro
networks:
net:
+52
View File
@@ -0,0 +1,52 @@
services:
nginx:
container_name: ${APP_PREFIX}-${APP_ENV}-nginx
image: nginx:${DEPLOY_NGINX_TAG:-1.29.8-alpine-slim}
restart: always
working_dir: /etc/nginx/conf.d
env_file:
- .env
ports:
- "${APP_PORT}:80"
# depends_on:
# api:
# condition: service_started
healthcheck:
test: wget --no-verbose --tries=1 --spider http://localhost || exit 1
interval: 5m
timeout: 3s
retries: 3
start_period: 2m
volumes:
- ./services/nginx/hosts/${NGINX_HOSTS}:/etc/nginx/templates
- ./services/nginx/.htpasswd:/etc/nginx/.htpasswd
- /etc/localtime:/etc/localtime:ro
networks:
net:
db:
container_name: ${APP_PREFIX}-${APP_ENV}-db
image: postgres:${DEPLOY_POSTGRES_TAG:-18.3-alpine3.23}
restart: always
environment:
POSTGRES_USER: ${DB_USERNAME}
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DATABASE: ${DB_DATABASE}
healthcheck:
test: [ "CMD-SHELL", "pg_isready -U ${DB_USERNAME} -d ${DB_DATABASE}" ]
interval: 5s
timeout: 2s
retries: 5
volumes:
- db:/var/lib/postgresql
- /etc/localtime:/etc/localtime:ro
networks:
net:
volumes:
db:
name: ${APP_PREFIX}-${APP_ENV}-db
networks:
net:
name: ${APP_PREFIX}-${APP_ENV}-net
+92
View File
@@ -0,0 +1,92 @@
<?php
/**
* Select foreign key in edit form
* @link https://www.adminer.org/plugins/#use
* @author WiRight, IDSMK
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerIDSMKEditForeign extends Adminer\Plugin {
protected $limit;
function __construct($limit = 0) {
$this->limit = $limit;
}
function editInput($table, $field, $attrs, $value) {
static $foreignTables = [];
static $values = [];
$foreignKeys = &$foreignTables[$table];
if ($foreignKeys === null) {
$foreignKeys = Adminer\column_foreign_keys($table);
}
$titleFields = [
'name',
'title',
'nickname',
'email',
];
$titleFieldName = null;
foreach ((array) $foreignKeys[$field["field"]] as $foreignKey) {
if (count($foreignKey["source"]) == 1) {
$target = $foreignKey["table"];
$id = $foreignKey["target"][0];
$options = &$values[$target][$id];
if (!$options) {
$column = Adminer\idf_escape($id);
if (preg_match('~binary~', $field["type"])) {
$column = "HEX($column)";
}
$selectFields = [
$column,
];
$targetFields = array_keys(Adminer\fields($target));
foreach ($targetFields as $targetField) {
if (in_array($targetField, $titleFields)) {
$selectFields[] = Adminer\idf_escape($targetField);
$titleFieldName = $targetField;
break;
}
}
$rows = Adminer\get_rows('SELECT ' . implode(',', $selectFields) . ' FROM ' . Adminer\table($target) . ' ORDER BY 1');
$options = [
'',
];
foreach ($rows as $row) {
$options[$row[$id]] = $row[$titleFieldName ?? $id];
}
if ($this->limit && count($options) - 1 > $this->limit) {
return;
}
}
return "<select$attrs>" . Adminer\optionlist($options, $value, true) . "</select>";
}
}
}
protected $translations = [
'cs' => ['' => 'Výběr cizího klíče v editačním formuláři'],
'de' => ['' => 'Wählen Sie im Bearbeitungsformular den Fremdschlüssel aus'],
'pl' => ['' => 'Wybierz klucz obcy w formularzu edycji'],
'ro' => ['' => 'Selectați cheia străină în formularul de editare'],
'ja' => ['' => '外部キーを編集フォームで選択'],
'ru' => ['' => 'Выбор внешнего ключа при редактировании таблицы (с подстановкой Title)'],
];
}
+1
View File
@@ -0,0 +1 @@
asmkuser:$apr1$95jzw9DR$qCcDTA8jp2tges/mk8Hyg1
@@ -0,0 +1,15 @@
server {
listen 80;
server_name adminer.${APP_HOST};
client_max_body_size 50M;
location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://adminer:8080;
}
}
@@ -0,0 +1,21 @@
server {
listen 80;
server_name api.${APP_HOST};
client_max_body_size 500m;
location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_http_version 1.1;
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 86400s;
chunked_transfer_encoding on;
proxy_pass http://api:8080;
}
}
@@ -0,0 +1,27 @@
server {
listen 80 default_server;
server_name ${APP_HOST};
client_max_body_size 500m;
location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://web:3000;
}
location /_nuxt/ {
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_pass http://web:3000;
}
}
@@ -0,0 +1,15 @@
server {
listen 80;
server_name api.${APP_HOST};
client_max_body_size 500m;
location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://api:8080;
}
}
@@ -0,0 +1,15 @@
server {
listen 80 default_server;
server_name ${APP_HOST};
client_max_body_size 500m;
location / {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://web:3000;
}
}
+2
View File
@@ -0,0 +1,2 @@
*
!.gitignore