Документ объясняет, как вносить изменения в проект Gitea.
Предполагается, что вы следовали инструкциям по установке.
Острые вопросы безопасности следует сообщать на security@gitea.io.
Для настройки IDE для разработки Gitea см. конфигурации IDE, внесенные сообществом.
Пожалуйста, проведите поиск по проблемам в системе отслеживания с использованием различных ключевых слов, чтобы убедиться, что ваша проблема еще не была сообщена.
Если ваша проблема еще не была сообщена, откройте проблему
и ответьте на вопросы, чтобы мы могли понять и воспроизвести проблемное поведение.
Пожалуйста, напишите ясные и краткие инструкции, чтобы мы могли воспроизвести поведение — даже если это кажется очевидным.
Чем более подробно и конкретно вы описываете проблему, тем быстрее мы сможем её исправить.
Очень полезно, если вы сможете воспроизвести вашу проблему на сайте, работающем на последних коммитах, например, https://demo.gitea.com, так как возможно, что ваша проблема уже была исправлена в текущей версии.
Пожалуйста, следуйте указаниям, описанным в Как эффективно сообщать о багах, для вашего отчета.Пожалуйста, будьте добры, помните, что Gitea предоставляется вам бесплатно, и вы получаете бесплатную поддержку.
Обычно проблемы относятся к одной из следующих категорий:
bug
: Что-то в фронтенде или бэкенде работает неожиданноsecurity issue
: Уязвимость, которая имеет серьёзные последствия, такие как утечка данных другого пользователя. Пожалуйста, не сообщайте такие проблемы на публичный трекер и отправьте письмо на security@gitea.io вместо этогоfeature
: Полностью новая функциональность. Вы должны описать эту функцию в достаточной детали, чтобы любой, кто прочитает проблему, мог понять, как она должна быть реализованаenhancement
: Существующая функция должна быть улучшенаrefactoring
: Части базы кода не соответствуют другим частям и должны быть изменены для улучшения поддерживаемости GiteaЕсли вы хотите изменить или добавить что-то, пожалуйста, сообщите всем, что вы работаете над этим — откройте проблему или оставьте комментарий к существующей проблеме перед началом работы! Основные изменения, такие как новые функции, должны пройти через процесс предложений изменений перед тем, как будут приняты. Это в основном для того, чтобы избежать проблем, связанных с внедрением, только чтобы обнаружить, что ваше предложенное внедрение имеет некоторые потенциальные проблемы. Кроме того, этот процесс дает всем возможность проверить дизайн, помогает предотвратить дублирование усилий и гарантирует, что идея соответствует целям проекта и инструментам.Запросы на вытягивание (pull requests) не должны использоваться для обсуждения архитектуры.
Комментирование закрытых или объединённых задач/запросов на вытягивание (PR) строго не рекомендуется. Такие комментарии могут быть пропущены, так как некоторые поддерживатели могут не просматривать уведомления для закрытых задач, полагая, что проблема решена. Поэтому, комментирование закрытых/объединённых задач/запросов на вытягивание (PR) может быть отключено до запланированного автоматического закрытия, если начинается обсуждение или если постятся несвязанные комментарии. Если требуется дальнейшее обсуждение, мы рекомендуем вам открыть новую задачу и рекомендуем ссылаться на задачу/запрос на вытягивание (PR) для контекста.
См. инструкции по настройке разработки.
Зависимости Go управляются с помощью Go Modules. Вы можете найти больше информации в документации Go mod и Wiki Go Modules.
Запросы на вытягивание (pull requests) должны изменять только go.mod
и go.sum
, если это связано с вашим изменением, будь то исправление ошибки или новая функция.
Кроме того, эти файлы должны изменяться только запросами на вытягивание (pull requests), единственной целью которых является обновление зависимостей.Обновление go.mod
, go.sum
должно быть обосновано в описании запроса на вытягивание (pull request), и должно быть проверено проверяющими и/или сливающими, чтобы всегда ссылаться на существующий коммит вверху.
Для внешней части мы используем npm.
Те же ограничения применяются для внешних зависимостей, как и для внутренних, с исключениями, что файлы для них — package.json
и package-lock.json
, и что новые версии всегда должны ссылаться на существующую версию.
В зависимости от вашего изменения, пожалуйста, прочитайте:
Вы всегда должны запускать make fmt
перед коммитом, чтобы соответствовать стилю Gitea.
Новые файлы кода, которые вы добавляете, должны использовать стандартный заголовок авторского права:
// Copyright <текущий год> The Gitea Authors. Все права защищены.
// SPDX-License-Identifier: MIT
После этого, авторское право должно изменяться только при смене автора.
Перед отправкой pull request, запустите все тесты, чтобы убедиться, что ваши изменения не вызывают регрессии в других местах.Вот как запустить тестовый набор:
make lint |
проверяет все (не требуется, если вы меняете только фронтенд или бэкенд) |
make lint-frontend |
проверяет файлы фронтенда |
make lint-backend |
проверяет файлы бэкенда |
Команда | Действие | |
---|---|---|
make test[\#SpecificTestName] |
запускает юнит-тесты | |
make test-sqlite[\#SpecificTestName] |
запускает интеграционные тесты для SQLite | Дополнительные сведения |
make test-e2e-sqlite[\#SpecificTestName] |
запускает тесты end-to-end для SQLite | Дополнительные сведения |
Все переводы происходят на Crowdin.
Единственный перевод, который поддерживается в этом репозитории, это английский перевод.
Он регулярно синхронизируется с Crowdin.
Другие локали на основной ветке не должны обновляться вручную, так как они будут перезаписаны при каждой синхронизации.
Как только язык достигнет удовлетворительного процента переведенных ключей (~25%), он будет синхронизирован обратно в этот репозиторий и включен в следующую версию.Инструмент go run build/backport-locale.go
можно использовать для переноса локалей с основной ветки на ветки релизов, которые были пропущены.## Проверка кода
Пожалуйста, постарайтесь сделать свой запрос на слияние удобным для проверки.
Для этого ознакомьтесь с Руководством по лучшим практикам для более быстрых проверок.
В нем содержится множество полезных советов для любых проектов, в которые вы можете внести свой вклад.
Некоторые ключевые моменты:
В заголовке запроса на слияние опишите проблему, которую вы исправляете, а не то, как вы её исправили.
Используйте первый комментарий как краткое описание вашего запроса на слияние.
В кратком описании запроса на слияние вы можете описать, как именно вы исправили эту проблему.
Обновляйте это краткое описание по мере эволюции запроса на слияние.
Если ваш запрос на слияние изменяет пользовательский интерфейс, вы должны добавить после скриншоты в кратком описании запроса на слияние.
Если вы не внедряете новую функцию, вы также должны добавить до скриншоты для сравнения.
Если вы внедряете новую функцию, ваш запрос на слияние будет объединен только если ваши скриншоты обновлены.
Кроме того, запросы на слияние с новыми функциями будут объединены только если их краткое описание содержит ясное описание использования (понятное для пользователей) и описание тестирования (понятное для проверяющих).
Вы должны стремиться объединить оба в одно описание.Еще одно требование для объединения запросов на слияние заключается в том, чтобы запрос был правильно помечен.
Однако это не ваша задача как вкладчика, а задача лица, объединяющего ваш запрос на слияние.
Если вы считаете, что ваш запрос на слияние был неправильно помечен, или заметили, что он был объединен без меток, пожалуйста, сообщите нам об этом.Если ваш запрос на слияние закрывает некоторые проблемы, вы должны указать это в форме, понятной как GitHub, так и Gitea, то есть добавив абзац вида
Fixes/Closes/Resolves #<ISSUE_NR_X>.
Fixes/Closes/Resolves #<ISSUE_NR_Y>.
Добавь к твоему резюме.
Каждый закрытый issue должен находиться на отдельной строке.
PR должен быть привязан к майлстоуну только в том случае, если он, вероятно, будет влит в данную версию.
Как правило, предполагается, что PR останется открытым на дополнительный месяц за каждые OnClickListener добавленных строк.
PR без привязки к майлстоуну могут не быть влиты.
practically all labels used inside Gitea можно классифицировать как один из следующих:- modifies/…
: Определяет, какие части кодовой базы затронуты. Эти теги будут установлены через CI.
topic/…
: Определяет концептуальную компоненту Gitea, затронутую, то есть issues, проекты или аутентификацию. Лучше всего PR должен затрагивать только одну компоненту, но может быть пересечение. Теги должны быть установлены вручную.type/…
: Определяет тип issue или PR (функциональность, рефакторинг, документация, баг и т.д.). Если GitHub поддерживал бы scoped labels, эти теги были бы эксклюзивными, поэтому вы должны установить ровно один, не больше и не меньше (каждый PR должен входить в одну из предоставленных категорий, и только одну).issue/…
/ pr/…
: Теги, специфичные для issues или PR соответственно, и необходимые только в данном контексте, то есть issue/not-a-bug
или pr/need-2-approvals
Каждый PR должен быть правильно отмечен всеми применимыми тегами.Также есть некоторые теги, которые будут управляться автоматически.
В частности, это
backport
или необходимость в ручном backportPR считается разрушающим, если он соответствует одному из следующих критериев:
app.ini
)В частности, это означает, что добавление новых настроек не является разрушающим.
Изменение значения по умолчанию настройки или замена настройки другой является разрушающим.
Если ваш PR содержит разрушающее изменение, вы должны добавить два элемента в резюме вашего PR:
BREAKING
, объясняющий простыми словами (понятными для типичного пользователя), как этот PR влияет на пользователей и как смягчить эти изменения. Этот раздел может выглядеть, например, как```md
Момент создания обычного PR или конвертации чернового PR в обычный — это момент начала код-ревью. \
Как только это произошло, больше не следует делать rebase или squash веток, так как это затрудняет просмотр новых изменений. \
Объединяйте основную ветку в вашу ветку только в том случае, если это действительно необходимо, например, из-за конфликтов изменений в это время. \
Это уменьшает ненужные запуски CI. \
Не беспокойтесь о коммитах слияния, которые могут нарушить историю ваших коммитов, так как каждый PR будет объединен с squash. \
Это означает, что все изменения будут объединены в один новый коммит, чье сообщение будет таким, как описано ниже.
### Объединение PR
Изменения в Gitea должны быть проверены перед тем, как быть принятыми — независимо от того, кто их вносит, даже если это владелец или поддерживатель. \
Единственным исключением являются критические ошибки, которые препятствуют компиляции или запуску Gitea. \
В частности, мы требуем двух одобрений от поддерживателей для каждого PR. \
Как только это условие выполнено, ваш PR получает метку `lgtm/done`. \
С этого момента ваша единственная ответственность — исправлять конфликты слияния или отвечать на/реализовывать запросы поддерживателей. \
Ответственность за объединение вашего PR с этого момента лежит на поддерживателях.Если PR имеет метку `lgtm/done` и больше нет открытых обсуждений или конфликтов слияния, любой поддерживатель может добавить метку `reviewed/wait-merge`. \
Эта метка означает, что PR является частью очереди слияний и будет объединен как можно скорее. \
Очередь слияний будет очищена в следующем порядке:
<https://github.com/go-gitea/gitea/pulls?q=is%3Apr+label%3Areviewed%2Fwait-merge+sort%3Acreated-asc+is%3Aopen>
Gitea использует свой собственный инструмент, <https://github.com/GiteaBot/gitea-backporter>, чтобы автоматизировать части процесса проверки. \
Этот инструмент автоматически выполняет следующие действия:
- создает PR для обратной совместимости, если это необходимо, после объединения исходного PR;
- удаляет PR из очереди слияний после объединения PR;
- поддерживает самую старую ветку в очереди слияний обновленной слияниями.
### Конечный звон
Если PR был проигнорирован более семи дней без комментариев или проверок, и автор или любой поддерживатель считает, что PR не выдержит длительного ожидания (например, PR по рефакторингу), они могут отправить "конечный звон" в TOC, упомянув их в комментарии. После еще семи дней, если одобрений по-прежнему нет, это считается вежливым отказом, и запрос на слияние будет закрыт, чтобы избежать дальнейшего траты времени. Поэтому, "окончательный звонок" имеет стоимость и должен использоваться осторожно.Однако, если у поддерживателей нет возражений, запрос на слияние может быть объединён с одобрением только от TOC (не автора).
### Сообщения коммитов
Слиятели могут и должны переписывать заголовок запроса на слияние и его краткое описание (первый комментарий запроса на слияние), чтобы при необходимости создать легко понимаемое сообщение коммита. \
Конечное сообщение коммита больше не должно содержать неопределенности, например, `надеюсь, <x> больше не произойдет`. Неопределенность следует заменить на определенность.
#### Соавторы запроса на слияние
Человек считается соавтором запроса на слияние в тот момент, когда он (соавтор) создал коммит, который не является просто коммитом слияния основной ветки в ветку. \
Слиятели должны удалять таких "ложноположительных" соавторов при написании сообщения коммита. \
Истинные соавторы должны оставаться в сообщении коммита.
#### Запросы на слияние, направленные на `main`
Сообщение коммита запросов на слияние, направленных на `main`, всегда имеет следующий формат:
```bash
$PR_TITLE ($PR_INDEX)
$REWRITTEN_PR_SUMMARY
Сообщение коммита запросов на обратную совместимость всегда имеет следующий формат:
$PR_TITLE ($INITIAL_PR_INDEX) ($BACKPORT_PR_INDEX)
$REWRITTEN_PR_SUMMARY
Каталог документов в основном репозитории будет удален в какой-то момент. У нас будет YAML-файл для хранения метаданных конфигурационных файлов. После завершения этого процесса, документация по конфигурации должна находиться в основном репозитории.## API v1
API документирован с помощью swagger и основан на API GitHub.
API Gitea должен использовать те же конечные точки и поля, что и API GitHub, по возможности, если нет убедительных причин отклоняться.
Если Gitea предоставляет функциональность, которой нет в GitHub, можно создать новую конечную точку.
Если Gitea предоставляет информацию, которой нет в API GitHub, можно использовать новое поле, которое не будет конфликтовать с любыми полями GitHub.
Обновление существующего API не должно удалять существующие поля, если нет действительно убедительных причин для этого.
То же самое относится к ответам о состоянии. Если вы заметили проблему, не стесняйтесь оставить комментарий в коде для будущей переработки в API v2 (который в настоящее время не планируется).### Добавление/поддержка API-маршрутовВсе ожидаемые результаты (ошибки, успех, сообщения об ошибках) должны быть документированы (пример).
Все типы ввода JSON должны быть определены как структуры в modules/structs/ (пример)
и ссылаться в routers/api/v1/swagger/options.go.
Они могут быть использованы, как в этом примере.
Все JSON-ответы должны быть определены как структуры в modules/structs/ (пример)
и ссылаться в своей категории в routers/api/v1/swagger/ (пример)
Они могут быть использованы, как в этом примере.### Когда использовать тот или иной HTTP-метод
В общем, HTTP-методы выбираются следующим образом:
Все параметры конечных точек, изменяющих/редактирующих объект, должны быть необязательными (кроме тех, которые идентифицируют объект, которые являются обязательными).
Конечные точки, возвращающие списки, должны
page
& limit
опции в запросе)X-Total-Count
через SetTotalCountHeader (пример)Мы переносим PRs при следующих обстоятельствах:1. Активен режим заморозки функций, но версия <version>-rc0
ещё не была выпущена. Здесь мы переносим как можно больше.
2. Версия rc0
уже выпущена. Здесь мы переносим только исправления ошибок и уязвимостей безопасности, а также небольшие улучшения. Большие PRs, такие как рефакторы, больше не переносятся.
3. Мы никогда не переносим новые функции.
4. Мы никогда не переносим разрушительные изменения, за исключением случаев, когда
1. Разрушительное изменение не оказывает влияния на большинство пользователей
2. Компонент, вызывающий разрушительное изменение, помечен как экспериментальный
В прошлом было необходимо вручную осуществлять перенос PRs.
Теперь это не обязательно, так как наш бот переноса автоматически создаёт переносы после слияния PR, если PR
backport/manual
backport/<version>
Метка backport/manual
означает, что вы хотите самостоятельно осуществить перенос изменений или что возникли конфликты при переносе, поэтому вы должны сделать это самостоятельно.
Заголовок PR переноса должен быть
<оригинальный заголовок PR> (#<оригинальный номер PR>)
Первые две строки описания PR переноса должны быть
Перенос #<оригинальный номер PR>
остальная часть описания и меток должна соответствовать оригинальному PR.### Передачи
Передачи осуществляются точно так же, как описано выше для переносов.
Мы рассматриваем действие внесения вклада в код путём отправки Pull Request как "Подпись" или согласие с сертификатами и условиями DCO и лицензией MIT.
Дополнительные действия не требуются.
Вы также можете решить подписать свои коммиты, добавив следующую строку в конец ваших сообщений коммитов:
Подпись: Joe Smith <joe.smith@email.com>
Если вы установите параметры конфигурации Git user.name
и user.email
, вы можете автоматически добавить строку в конец ваших коммитов с помощью git commit -s
.
Мы предполагаем в добрых намерениях, что предоставленная вами информация является юридически обязательной.## Цикл выпускаМы внедрили расписание выпусков, чтобы упростить процесс работы над, завершения и выпуска версий.
Основная цель — выпускать основные версии каждые три или четыре месяца, что включает два или три месяца общего развития, за которыми следует один месяц тестирования и доводки, известный как заморозка выпуска.
Все запросы на включение новых функций (feature pull requests) должны быть слингованы до начала заморозки функций. Все запросы на включение новых функций, которые не были слингованы до начала заморозки функций, будут перенесены на следующий этап, обратите внимание на нашу публикацию о заморозке функций на Discord. И, во время замороженного периода, соответствующая ветка выпуска открыта для исправлений, перенесённых из основной ветки. Кандидаты на выпуск создаются в этот период для тестирования пользователей, чтобы получить окончательную версию, которая поддерживается в этой ветке.Во время цикла разработки мы также можем выпускать любые необходимые мелкие версии
для предыдущей версии. Например, если последний выпущенный релиз —
v1.2, то мелкие изменения для предыдущей версии — например, v1.1.0 -> v1.1.1 —
все ещё возможны.
Каждый запрос на включение должен быть проверен по крайней мере двумя модераторами (или владельцами) перед тем, как его можно будет слинговать.
Для запросов на рефакторинг после недели и запросов на включение только документации достаточно одобрения одного модератора.
Модератором должен быть вкладчик Gitea, который внес не менее четырёх принятых запросов на включение. Вкладчик должен подать заявку на должность модератора в Discord #develop
канале. Команда модераторов может пригласить вкладчика. Модератор должен уделять время проверке кода. Если модератору нет времени для этого, он должен подать заявку на выход из команды модераторов и мы дадим ему честь быть членом команды советников. Конечно, если советник имеет время для проверки кода, мы с радостью приветствуем его возвращение в команду модераторов. Если модератор неактивен более трёх месяцев и забыл выйти из команды модераторов, владельцы могут перенести его или её из команды модераторов в команду советников.
По соображениям безопасности, модераторы должны использовать двухфакторную аутентификацию (2FA) для своих аккаунтов и, если возможно, предоставлять подписанные GPG коммиты.
https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/
https://help.github.com/com/articles/signing-commits-with-gpg/Кроме того, любой аккаунт с правом записи (например, боты и члены TOC) должен использовать двухфакторную аутентификацию (2FA).
https://help.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/## Комитет технического надзора (TOC)
В начале 2023 года команда Owners
была распущена. Вместо этого устав управления предложил создать комитет технического надзора (TOC), который расширяет команду владельцев проекта Gitea с трёх избираемых позиций до шести позиций. Три позиции избираются, как это было в предыдущие годы, а три других позиции занимают назначенные члены компании Gitea.
https://blog.gitea.com/quarterly-23q1/
Любой поддерживатель может быть частью общественного TOC, если он не связан с компанией Gitea. Поддерживатель может либо выдвинуть себя кандидатом, либо быть выдвинутым другими поддерживателями для участия в выборах TOC. Если вас выдвинули другие лица, вы должны принять своё выдвижение до начала голосования, чтобы стать кандидатом.
TOC избирается на один год, выборы TOC происходят ежегодно.
После объявления результатов выборов TOC избранные члены имеют две недели для подтверждения или отказа от места.
Если избранный член не ответит в течение этого времени, он автоматически считается отказавшимся от места.
Отказы приводят к тому, что человек с наибольшим количеством голосов, следующий за ним, получает такое же право.
Пока места в TOC остаются пустыми, члены предыдущего TOC могут их занять до тех пор, пока избранный член не примет место.Если избранный член, принявший место, ещё не настроил 2FA, он будет временно считаться ожиданием ответа
до тех пор, пока он не настроит 2FA, что оставляет его место пустым на этот период времени.
Вот история владельцев и сроки их службы:
Каждый член сообщества, избранного TOC (Technical Oversight Committee), будет получать по $500 в месяц в качестве компенсации за свою работу.
Кроме того, любой менеджер выпуска сообщества для конкретного выпуска или LTS (Long-Term Support) будет компенсирован в размере $500 за доставку указанного выпуска.
Эти средства будут поступать из источников сообщества, таких как OpenCollective, а не напрямую от компании. Только лица, не являющиеся сотрудниками компании, имеют право на эту компенсацию. Если член TOC сообщества берет на себя обязанности менеджера выпуска, они будут компенсированы только за свои обязанности в TOC. Сотрудники Gitea Ltd не имеют права получать средства из OpenCollective, за исключением случаев возмещения затрат, связанных с покупкой для самого проекта Gitea.
С учетом того, что Gitea охватывает множество проектов за пределами основного репозитория, будут созданы несколько групп для помощи в сосредоточении на конкретных областях вместо того, чтобы требовать от поддерживателей быть универсальными специалистами. Поддерживатели, конечно, более чем приветствуются для участия в нескольких группах, если они хотят вносить вклад в нескольких местах. Текущие предложенные группы:- Основная группа: поддерживает основной репозиторий Gitea
Каждый год план действий обсуждается с командой поддержки Gitea, и обратная связь собирается от различных заинтересованных сторон. Члены TOC должны ежегодно проверять план действий и работать вместе над направлением проекта.
Когда требуется голосование за предложение или другое изменение, голоса избранных членов TOC сообществом учитываются немного больше, чем голоса избранных членов TOC компаниями. Такой подход позволяет избежать тупиков и гарантирует, что изменения соответствуют миссии и мнению сообщества.
Вы можете посетить наш план действий на вики.
У Gitea есть ветка main
как вершина версии и ветки версий, такие как release/v1.19
. Ветка release/v1.19
является веткой выпуска, и мы помечаем v1.19.0
для загрузки бинарников. Если v1.19.0
имеет ошибки, мы будем принимать pull-запросы на ветку release/v1.19
и выпускать тег v1.19.1
, после чего исправление ошибки также будет внесено в основную ветку.
Так как ветка main
является вершиной версии, если вы хотите использовать Gitea в производственной среде, пожалуйста, скачайте последнюю версию с тегом выпуска. Все ветки будут защищены через GitHub, все pull-запросы на каждую ветку должны быть проверены двумя поддерживателями и должны пройти автоматические тесты.## Выпуск Gitea — пусть $vmaj, $vmin и $vpat будут номерами основной, минорной и патч-версий соответственно, $vpat должен быть rc1, rc2, 0, 1, . . . . . . $vmaj. $vmin будет сохранен таким же, как майлстоны на GitHub или Gitea в будущем.
main
с PRs с меткой changelog
, и после того, как он будет слит, выполните следующие шаги:
-dev
как git tag -s -F release. notes v$vmaj. $vmin. 0-dev
и отправьте тег как git push origin v$vmaj. $vmin. 0-dev
.release/v$vmaj. $vmin
.release/v$vmaj. $vmin
и подождите, пока он будет проверен и слит.git tag -s -F release. notes v$vmaj. $vmin. $vpat
(файл release. notes может быть временным файлом, который включает только changelog этой версии, которую вы добавили в CHANGELOG.md
).git push origin v$vmaj. $vmin. $vpat
. Drone CI автоматически создаст выпуск и загрузит все скомпилированные бинарные файлы. (Но в настоящее время он автоматически не добавляет заметки к выпуску. Возможно, стоит это исправить.)- Если необходимо, отправьте PR для передачи changelog на ветку main
и обновите версию в docs/config.yaml
, чтобы ссылаться на новую версию.#announcements
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )