From 345606c11253ea510d56eac9fe3c67e192f2d122 Mon Sep 17 00:00:00 2001 From: Maxim Kramarenko Date: Wed, 12 Aug 2026 13:37:45 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A4=D0=B0=D0=B9=D0=BB=D1=8B=20=D1=81=D0=BE?= =?UTF-8?q?=D0=BE=D0=B1=D1=89=D0=B5=D1=81=D1=82=D0=B2=D0=B0,=20=D1=88?= =?UTF-8?q?=D0=B0=D0=B1=D0=BB=D0=BE=D0=BD=D1=8B,=20dependabot=20=D0=B8=20w?= =?UTF-8?q?orkflow=20=D1=80=D0=B5=D0=BB=D0=B8=D0=B7=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Метрика community profile у репозитория была 42%: из обязательного набора присутствовали только README, LICENSE и description. Добавлено: - SECURITY.md — приватный канал через GitHub Security Advisories, сроки ответа, список приоритетных классов уязвимостей для системы с ACL. Отдельно перечислено то, что уязвимостью не является: root/root в docker-compose, .env в репозитории, исполнение BeanShell-скриптов - CONTRIBUTING.md — сборка через Docker и через Gradle, стиль кода, правила миграций Liquibase, список изменений, требующих архитектурного ревью. Честно сказано, что все тест-классы сейчас под @Ignore - CODE_OF_CONDUCT.md — Contributor Covenant 2.1 - шаблоны issue (баг и улучшение) и pull request. Шаблон бага требует версию, способ развертывания и логи — этого не хватало в существующих обращениях - .github/dependabot.yml — gradle и github-actions ежемесячно. Обновления сгруппированы и ограничены пятью PR, иначе на таком объеме старых зависимостей репозиторий завалит пулл-реквестами. Struts исключен: 1.3.10 снят с поддержки в 2013, уход с него — отдельная задача, а не обновление версии - .github/workflows/release.yml — по пушу тега v* собирает WAR, публикует образ в ghcr.io/maximkr/trackstudio и создает GitHub Release с WAR во вложении. Имя пакета GHCR задано в нижнем регистре явно: реестр не принимает заглавные буквы, а github.repository содержит TrackStudio Синтаксис всех YAML проверен парсером. Co-Authored-By: Claude Opus 5 --- .github/ISSUE_TEMPLATE/bug_report.yml | 71 +++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 11 +++ .github/ISSUE_TEMPLATE/feature_request.yml | 46 ++++++++++ .github/dependabot.yml | 41 +++++++++ .github/pull_request_template.md | 24 +++++ .github/workflows/release.yml | 101 +++++++++++++++++++++ CODE_OF_CONDUCT.md | 73 +++++++++++++++ CONTRIBUTING.md | 95 +++++++++++++++++++ SECURITY.md | 49 ++++++++++ 9 files changed, 511 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 .github/dependabot.yml create mode 100644 .github/pull_request_template.md create mode 100644 .github/workflows/release.yml create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 SECURITY.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..67ae37a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,71 @@ +name: Сообщить об ошибке +description: Что-то работает не так, как должно +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + Спасибо за отчёт. Чем точнее шаги воспроизведения, тем быстрее получится починить. + + **Нашли уязвимость?** Не описывайте её здесь — воспользуйтесь [приватной формой](https://github.com/maximkr/TrackStudio/security/advisories/new), см. [SECURITY.md](https://github.com/maximkr/TrackStudio/blob/main/SECURITY.md). + + - type: textarea + id: what-happened + attributes: + label: Что происходит + description: Опишите проблему и что вы ожидали увидеть вместо этого. + validations: + required: true + + - type: textarea + id: steps + attributes: + label: Шаги воспроизведения + placeholder: | + 1. Войти как ... + 2. Открыть задачу ... + 3. Нажать ... + 4. Появляется ошибка ... + validations: + required: true + + - type: input + id: version + attributes: + label: Версия TrackStudio + description: "Вывод `./gradlew printVersion` или значение `trackstudio.version` из развёрнутого приложения. Если неизвестна — укажите дату сборки или хеш коммита." + placeholder: "v6.0.0-56-g1764993" + validations: + required: true + + - type: dropdown + id: deployment + attributes: + label: Способ развёртывания + options: + - Docker Compose + - Kubernetes + - Ручная установка в Tomcat + - Другое + validations: + required: true + + - type: input + id: environment + attributes: + label: Окружение + description: Версия PostgreSQL, ОС хоста, браузер — то, что относится к делу. + placeholder: "PostgreSQL 17, Ubuntu 24.04, Firefox 130" + + - type: textarea + id: logs + attributes: + label: Логи + description: "Относящийся к делу фрагмент из `docker compose logs trackstudio` или из логов Tomcat. Стектрейс целиком, если он есть." + render: text + + - type: textarea + id: extra + attributes: + label: Дополнительно + description: Скриншоты, обходные пути, всё, что может помочь. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..1b79b98 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,11 @@ +blank_issues_enabled: true +contact_links: + - name: Вопрос по установке или использованию + url: https://github.com/maximkr/TrackStudio/discussions + about: Для вопросов, а не для багов — обсуждения подходят лучше. + - name: Документация + url: https://github.com/maximkr/TrackStudio/wiki + about: Руководства по установке и настройке. + - name: Сообщить об уязвимости + url: https://github.com/maximkr/TrackStudio/security/advisories/new + about: Приватный канал. Не описывайте уязвимости в публичных issue. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..d121b72 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,46 @@ +name: Предложить улучшение +description: Идея новой возможности или улучшения существующей +labels: ["enhancement"] +body: + - type: textarea + id: problem + attributes: + label: Какую задачу это решает + description: Опишите ситуацию, в которой сейчас неудобно. Что вы пытаетесь сделать и почему это не получается. + validations: + required: true + + - type: textarea + id: solution + attributes: + label: Как это могло бы работать + description: Ваше предложение. Если представляете интерфейс — опишите или приложите набросок. + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Что пробовали вместо этого + description: Обходные пути, настройки, скрипты — то, чем задача решается сейчас, если решается. + + - type: dropdown + id: area + attributes: + label: Какой части системы касается + options: + - Задачи и рабочие процессы + - Права доступа и роли + - Фильтры и отчёты + - Уведомления и подписки + - REST API и интеграции + - Интерфейс + - Развёртывание и администрирование + - Другое + + - type: checkboxes + id: contribution + attributes: + label: Участие + options: + - label: Я готов взяться за реализацию сам diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..237f66a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,41 @@ +version: 2 + +updates: + # Зависимости Gradle. Проект содержит много старых библиотек, поэтому + # обновления сгруппированы и ограничены по количеству PR — иначе dependabot + # завалит репозиторий десятками отдельных пулл-реквестов. + - package-ecosystem: gradle + directory: "/" + schedule: + interval: monthly + open-pull-requests-limit: 5 + groups: + logging: + patterns: + - "org.slf4j:*" + - "ch.qos.logback:*" + hibernate: + patterns: + - "org.hibernate:*" + lucene: + patterns: + - "org.apache.lucene:*" + minor-and-patch: + update-types: + - minor + - patch + ignore: + # Struts 1.3.10 снят с поддержки в 2013 году, новых версий не будет. + # Уход с него — отдельная большая задача, а не обновление зависимости. + - dependency-name: "org.apache.struts:*" + + # Версии GitHub Actions в workflow + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: monthly + open-pull-requests-limit: 5 + groups: + actions: + patterns: + - "*" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..c5b68df --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,24 @@ + + +## Что меняется + + + +## Связанные issue + + + +## Как проверить + + + +## Скриншоты + + + +## Чек-лист + +- [ ] `./gradlew build` проходит локально +- [ ] Изменения схемы БД оформлены миграцией Liquibase (или схема не менялась) +- [ ] Обновлена документация — `README.md`, `docs/`, `AGENTS.md` (или не требуется) +- [ ] Изменение не затрагивает пункты из раздела «Требуют архитектурного ревью» в [CONTRIBUTING.md](../CONTRIBUTING.md), либо это обсуждалось в issue diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..b68d749 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,101 @@ +name: Release + +# Запускается при пуше тега вида v6.0.1 +# git tag v6.0.1 && git push origin v6.0.1 +on: + push: + tags: + - 'v*' + +permissions: + contents: write # создать GitHub Release + packages: write # запушить образ в GHCR + +jobs: + release: + name: WAR + Docker образ + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + # com.palantir.git-version определяет версию по тегам + fetch-depth: 0 + + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '21' + + - name: Set up Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Build WAR + run: ./gradlew --no-daemon build + + - name: Set up Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Docker meta + id: meta + uses: docker/metadata-action@v5 + with: + # Имя пакета в GHCR обязано быть в нижнем регистре, + # поэтому оно задано явно, а не через github.repository + images: ghcr.io/maximkr/trackstudio + tags: | + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=raw,value=latest + + - name: Build and push image + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + + # Ручные заметки пишем в файл: gh прикрепит их поверх автоматически + # сгенерированного списка изменений + - name: Подготовить описание релиза + run: | + cat > release-notes.md <<'EOF' + ## Установка + + ### Docker + + ```bash + docker run -d -p 8080:8080 ghcr.io/maximkr/trackstudio:TAG_PLACEHOLDER + ``` + + Приложению нужна PostgreSQL — готовая конфигурация в `docker-compose.yml`. + + ### WAR + + Приложенный `TrackStudio.war` разворачивается в Tomcat 9+ на JDK 21. + Подробности — в [README](https://github.com/maximkr/TrackStudio#readme) и [вики](https://github.com/maximkr/TrackStudio/wiki). + EOF + sed -i "s/TAG_PLACEHOLDER/${GITHUB_REF_NAME}/" release-notes.md + + - name: Create GitHub Release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release create "${GITHUB_REF_NAME}" \ + build/libs/TrackStudio.war \ + --title "${GITHUB_REF_NAME}" \ + --notes-file release-notes.md \ + --generate-notes diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..6bf502f --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,73 @@ +# Кодекс поведения участников + +## Наше обязательство + +Мы, участники и сопровождающие проекта, обязуемся сделать участие в сообществе свободным от притеснений для всех — независимо от возраста, телосложения, видимых или невидимых особенностей, гендерной идентичности и самовыражения, уровня опыта, образования, социально-экономического положения, национальности, внешности, расы, религии, сексуальной ориентации и идентичности. + +Мы обязуемся действовать и взаимодействовать так, чтобы сообщество оставалось открытым, доброжелательным, разнообразным и здоровым. + +## Наши стандарты + +Примеры поведения, которое создаёт здоровую среду: + +- проявление эмпатии и доброты к другим людям; +- уважение к чужому мнению, точке зрения и опыту; +- конструктивная обратная связь — и умение принимать её достойно; +- признание своих ошибок, извинения перед теми, кого они затронули, и извлечение уроков; +- ориентация на то, что лучше для сообщества в целом, а не только лично для нас. + +Примеры неприемлемого поведения: + +- сексуализированные высказывания, изображения и знаки внимания любого рода; +- троллинг, оскорбления, уничижительные комментарии, нападки на личность или на политические взгляды; +- публичные или личные притеснения; +- публикация чужой личной информации — физического адреса, электронной почты и прочего — без явного разрешения; +- любое иное поведение, которое обоснованно считается неуместным в профессиональной среде. + +## Обязанности сопровождающих + +Сопровождающие отвечают за разъяснение и применение этих стандартов и принимают справедливые корректирующие меры в ответ на поведение, которое считают неуместным, угрожающим, оскорбительным или вредным. + +Сопровождающие вправе удалять, редактировать и отклонять комментарии, коммиты, код, правки вики, issue и другие материалы, не соответствующие настоящему кодексу, и обязуются объяснять причины модерации, когда это уместно. + +## Область применения + +Кодекс действует во всех пространствах проекта, а также в случаях, когда человек официально представляет проект в публичном пространстве — например, пишет с официального адреса, с официального аккаунта в соцсетях или выступает как представитель проекта на мероприятии. + +## Применение + +О случаях оскорбительного, притесняющего или иного неприемлемого поведения сообщайте сопровождающему проекта — [@maximkr](https://github.com/maximkr). Все жалобы будут рассмотрены оперативно и справедливо. + +Сопровождающие обязаны уважать приватность и безопасность того, кто сообщил об инциденте. + +## Руководство по применению + +### 1. Исправление + +**Нарушение:** использование неуместных выражений или иное поведение, признанное непрофессиональным или нежелательным. + +**Последствие:** частное письменное предупреждение с разъяснением характера нарушения. Может быть запрошено публичное извинение. + +### 2. Предупреждение + +**Нарушение:** нарушение в результате одного инцидента или серии действий. + +**Последствие:** предупреждение с описанием последствий продолжения. Отсутствие взаимодействия с вовлечёнными лицами в течение определённого срока. Нарушение этих условий может привести к временному или постоянному запрету. + +### 3. Временный запрет + +**Нарушение:** серьёзное нарушение стандартов сообщества, в том числе устойчивое неприемлемое поведение. + +**Последствие:** временный запрет на любое взаимодействие и публичное общение с сообществом. Нарушение условий может привести к постоянному запрету. + +### 4. Постоянный запрет + +**Нарушение:** систематическое нарушение стандартов сообщества, притеснение отдельных лиц, агрессия или уничижение по отношению к группам людей. + +**Последствие:** постоянный запрет на любое публичное взаимодействие в рамках сообщества. + +## Атрибуция + +Настоящий кодекс основан на [Contributor Covenant](https://www.contributor-covenant.org/) версии 2.1, доступном по адресу https://www.contributor-covenant.org/version/2/1/code_of_conduct.html + +Руководство по применению вдохновлено [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..6f4dc1f --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,95 @@ +# Как участвовать в разработке TrackStudio + +Спасибо за интерес к проекту. Здесь описано, как собрать TrackStudio, что учитывать при изменениях и как оформить pull request. + +Если вы ИИ-агент или используете ассистента для работы с кодом — более подробные правила по архитектуре и стилю лежат в [`AGENTS.md`](AGENTS.md) и [`docs/architecture.md`](docs/architecture.md). + +## Быстрый старт + +Требуется Docker и Docker Compose. Всё остальное поднимается само. + +```bash +git clone https://github.com/maximkr/TrackStudio.git +cd TrackStudio +docker compose up -d --build +``` + +Приложение — http://localhost:8080, вход `root` / `root`. + +```bash +docker compose logs -f trackstudio # логи приложения +docker compose logs -f migrator # логи миграций Liquibase +docker compose down # остановить +docker compose down -v # остановить и удалить базу (данные пропадут) +``` + +## Сборка без Docker + +Нужен JDK 21. Gradle подтягивается wrapper-ом. + +```bash +./gradlew build # компиляция + тесты +./gradlew war # собрать TrackStudio.war +./gradlew printVersion # версия сборки +``` + +Версия определяется плагином `com.palantir.git-version` по git-тегам. Если собираете из shallow clone без тегов, вместо версии получится хеш коммита — при клонировании используйте полную историю. + +## Прежде чем браться за задачу + +- Загляните в [открытые issue](https://github.com/maximkr/TrackStudio/issues). Если задача уже описана — напишите в ней, что берётесь. +- Для крупных изменений сначала откройте issue с обсуждением. Так вы не потратите время на подход, который не подойдёт по архитектурным причинам. +- Изменения из списка ниже требуют предварительного обсуждения в любом случае. + +### Требуют архитектурного ревью + +Из `docs/architecture.md`, раздел 14: + +- изменение порядка захвата блокировок; +- изменения модели ACL; +- изменения структуры кешей и их инвалидации; +- процесс старта приложения и конфигурация; +- изменение контракта REST API. + +При таких изменениях обновите `docs/architecture.md` и `AGENTS.md` в том же PR. + +## Стиль кода + +Подробности — в [`AGENTS.md`](AGENTS.md). Коротко: + +- классы `PascalCase`, методы `camelCase`, константы `UPPER_SNAKE_CASE`, пакеты в нижнем регистре; +- таблицы БД — с префиксом `gr_`; +- логирование через SLF4J API: `org.slf4j.Logger` и `LoggerFactory`. Новый код на commons-logging не пишем; +- порядок импортов: `java`, затем `javax`, затем `org.apache`, затем `com.trackstudio`; +- кодировка исходников и ресурсов — UTF-8; +- в kernel-коде — только Lock API (`LockManager`, `ReadWriteLock`), не смешивать блокировки и `synchronized` в одном методе; +- наружу отдавать копии или неизменяемые представления, внутренние коллекции не публиковать. + +## Изменения схемы базы + +Только через Liquibase, каталог `liquibase/`. Правки схемы без миграции не принимаются. Учитывайте, что changelog разделён по языкам — `changelog-master-en.xml` и `changelog-master-ru.xml`. + +## Тесты + +Проект использует JUnit 4, тесты лежат в `src/test/java/`. + +```bash +./gradlew test +./gradlew test --tests "com.trackstudio.kernel.manager.IndexManagerTest" +``` + +Честное предупреждение: сейчас все существующие тест-классы помечены `@Ignore`, то есть фактически выполняется ноль тестов. Новый код с тестами приветствуется особенно — это то место, где проект больше всего нуждается в помощи. + +## Pull request + +1. Ответвитесь от `main`, ветку называйте осмысленно: `fix/...`, `feature/...`, `docs/...`. +2. Убедитесь, что `./gradlew build` проходит локально. +3. Опишите в PR, что меняется и зачем. Для изменений в UI приложите скриншоты до и после. +4. Дождитесь зелёного CI — на каждый PR запускаются сборка с тестами, сборка Docker-образа и анализ CodeQL. +5. Один PR — одно логическое изменение. Не смешивайте рефакторинг с исправлением бага. + +Коммиты пишите так, чтобы из заголовка было понятно, что сделано. Строгий формат не навязывается. + +## Лицензия + +Отправляя pull request, вы соглашаетесь, что ваш вклад распространяется на условиях [Apache License 2.0](LICENSE). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..4bb1ce1 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,49 @@ +# Политика безопасности + +## Поддерживаемые версии + +| Версия | Поддержка | +|--------|-----------| +| 6.x | ✅ исправления безопасности выпускаются | +| 5.x и ниже | ❌ коммерческие версии, не поддерживаются в этом репозитории | + +## Как сообщить об уязвимости + +**Не открывайте публичный issue для уязвимостей.** + +Воспользуйтесь приватным каналом GitHub: вкладка [**Security → Report a vulnerability**](https://github.com/maximkr/TrackStudio/security/advisories/new). Отчёт будет виден только сопровождающим репозитория. + +Если приватная форма по каким-то причинам недоступна, напишите сопровождающему — [@maximkr](https://github.com/maximkr). + +### Что приложить к отчёту + +- версию TrackStudio (см. `version.properties` в развёрнутом приложении или вывод `./gradlew printVersion`); +- способ развёртывания — Docker Compose, Kubernetes или ручная установка в Tomcat; +- шаги воспроизведения, желательно минимальные; +- что именно получает атакующий: чтение чужих задач, обход прав, выполнение кода, отказ в обслуживании; +- нужны ли для атаки учётные данные и какого уровня. + +### Сроки + +- **подтверждение получения** — в течение 5 рабочих дней; +- **предварительная оценка** — в течение 14 дней; +- исправление и публикация advisory — по договорённости, в зависимости от серьёзности. + +Мы просим не раскрывать детали публично, пока исправление не выпущено. + +## Что особенно интересно + +TrackStudio — многопользовательская система с иерархическими правами доступа, поэтому в первую очередь важны: + +- обход ACL: доступ к задачам, проектам или пользователям вне выданных прав; +- повышение привилегий через рабочие процессы, триггеры или скрипты; +- SQL-инъекции и инъекции в поисковые запросы Lucene; +- XSS в полях задач, комментариях и вложениях; +- проблемы аутентификации и управления сессиями в REST API (`/rest/*`); +- обход проверок при загрузке файлов. + +## Известные особенности, не являющиеся уязвимостями + +- **Учётные данные по умолчанию `root` / `root`** в docker-compose предназначены для локальной разработки. Смена пароля при развёртывании в продакшене — обязанность администратора. +- **Файл `.env` в репозитории** содержит пароль базы для локального запуска. Это не секрет продакшена, при развёртывании его нужно заменить. +- **BeanShell-скрипты и триггеры** выполняются намеренно и по определению позволяют исполнять код. Их доступность ограничивается правами администратора — это архитектурное решение, а не дефект.