├── .gitignore ├── .travis.yml ├── DevOpsHQ_new_project.png ├── LICENSE ├── README.md ├── README_EN.md ├── _config.yml ├── exampleproject ├── Main.py ├── __init__.py └── __main__.py ├── setup.cfg ├── setup.py └── tests ├── __init__.py ├── conftest.py └── test_Main.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # SageMath parsed files 80 | *.sage.py 81 | 82 | # dotenv 83 | .env 84 | 85 | # virtualenv 86 | .venv 87 | venv/ 88 | ENV/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | 103 | # JetBrains 104 | .idea/ -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: '3.6' 3 | branches: 4 | only: # можно перечислить ветки из которых должен быть автоматический запуск сборки на каждый push кода в репозиторий 5 | - master 6 | - develop 7 | install: # раздел предварительной настройки окружения до сборки 8 | - pip install pytest coverage codacy-coverage # эти библиотеки используются для запуска юнит-тестов сбора статистики покрытия кода юнит-тестами для сервиса Codacy 9 | script: # основной шаг сборки, состоящий из последовательного запуска скриптов 10 | - printenv # для отладки очень помогает вывод переменных окружения в логах Travis CI, потом этот шаг можно удалить 11 | - ls -la # также для отладки, потом этот шаг можно удалить 12 | - coverage run -m py.test tests # собираем покрытие кода тестами 13 | - coverage xml # формируем отчёт для Codacy 14 | - if [[ ! $CODACY_PROJECT_TOKEN ]]; then echo "Variable CODACY_PROJECT_TOKEN not set. Step is skipped."; exit 0; else python-codacy-coverage -r coverage.xml; fi # аплоадим отчёт в Codacy 15 | deploy: # раздел деплоя в котором можно указать действия, которые нужно произвести с успешно собранным артефактом 16 | provider: pypi # например, Travis CI поддерживает автоматическую загрузку в PyPI через указание провайдера "pypi" 17 | user: devopshq # логин проекта в PyPI 18 | password: # зашифрованный пароль для PyPI через утилиту travis-encrypt подставьте в переменную secure ниже: 19 | secure: "e5lg5iPHSMCIpjEGeA0XuJPHaqzwQjLJefIyjQpRNSgf7h9kYwKYI1BH3b8T48QUw6r099QYSgsTJF1pDNWw7rdpTfiXP7pjvr1esmSSr7fyKVeRYNjc/st0n+Blu99At8HEwLXtoLRw2zD92VvTeZA01qRakT0M1bXccT+6pP3FolG5q2HCvzhzImc+Q2FXPSYGgZIYUo28GoYdeVztq+cFwWd27Onx8ROVU0FrVbGQxYS84reiLuI5aCjlv26SJ+5UQREh/RkYnWbogDPSkN+ee+Cl6r+C3WAtf67ac/l++T1ejsv5G+hSyJlWDUrl+2YbTe0ul2b5szo0YY2uW+w+xEJqynGQp6mH0OBm3MCGvEaV8DEnbM94b6PXz1LHi8opWZAGIVSyst+W3w7jwIMU9kUi1leu8jgAcNPUHIC3UhJ7fJrJC4lElOAAn+cdtT5sb6eC4kIOVL3RjCtodeFLAHVWQxeIXnnR07paZPTN8Y4OpYhIY3fcisl5tLnzFnVZ3lf7W9KnAD8mzqxJsPLYEyqAcLxugpEntgL4gRmt/3R4eZz8XRxFvgh3O4m8u38eIwIWyd1FvY9ZfdrkUxfqWdESjz3tU6M4ZDlEVKdsfXtAr2QIxCA/OefprsuQCBtnyc14p1xfe0IiPXTnh5NaeuypZrKw2YaG/nct+tw=" 20 | distributions: sdist bdist_wheel # виды артефактов, которые нужно загрузить в PyPY, sdist загружает .tar.gz, bdist_wheel - загружает wheel-файл 21 | on: 22 | all_branches: true 23 | skip_cleanup: true 24 | after_script: # команды которые нужно выполнить после успешного окончания сборки и деплоя 25 | - echo "Deploy to PyPI finished." 26 | env: 27 | global: # здесь можно разместить общие переменные и секреты доступные для всех шагов сборки. Yапример, секрет для Codacy, зашифрованный через утилиту travis-encrypt подставьте в переменную secure ниже: 28 | - secure: "ZGjMqDQ7BE2Y/Aago40EpeRJWGM4SRt4PWmfFsRiDKJpkcXOpD+VXTDPHeCNVPrTg1O0PMVzfoEJAi1ST1ZnlJDmufelk9WjtZJFx5grUVAldcODrBQS7yuE5Ck9COExagHvQOmhu4G0EMnxxL1fv5UEc3ef+4513ve1YaKNctE8CjnTV1XCdaazKuDGBB49wuax7DynN/5D0hQYHw5rsxhwHY4YB4IXkjB74rTcp6tYF6FtFrhWioQ+K1aJOcfeqcwPjPGpY7VySmkh/iTxwAtkTrltVN3j9D2F5X276XEW5kFWm9B0x3ytztNkmJk0BSWH2za5QbhrOmRtIml52XnQVWWwDLUV7WgOpGiMEhdcvdlXA5i82uahSUL1svBfR4AQ8uI+e7NdTVkVHY5GvTq+Gd7u8Bp0QPenwMEif62mIZVVTk7IMq99JLLYAEE39K64rTZAivCaEqrfbX1ObMjyaMCeGP1Nu9evsEOM8DOsh8hMDU01gxSLUZFS0q+CKnRBsXEKhxtlNo6Wur260b23rJMrDeii2Q94OUmMbqus9qjZ8hwv5QEgDZgluZyOJsM1wLBqyn41FSBv3j7AiqA0o4RcROlg/paePBhX5NA1DpC1SOVs/E6P9Sio6vwvgQz28+oQ5tsw2jNxjM6cmzEpZFKj9Fe56IYA7pPi3tI=" 29 | -------------------------------------------------------------------------------- /DevOpsHQ_new_project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devopshq/ExampleProject/de6db39c1695d1e8e8eaec5eff019c3c69430912/DevOpsHQ_new_project.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Open DevOps Community 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ExampleProject 2 | ============== 3 | This is simple example of project in DevOpsHQ Community with basic functionality. 4 | See english instruction here: https://github.com/devopshq/ExampleProject/blob/master/README_EN.md 5 | 6 | [![ExampleProject build status](https://travis-ci.org/devopshq/ExampleProject.svg)](https://travis-ci.org/devopshq/ExampleProject) [![ExampleProject code quality](https://api.codacy.com/project/badge/Grade/63aaf7dcbeda43f0b7eb1d70be4ed36b)](https://www.codacy.com/app/tim55667757/ExampleProject/dashboard) [![ExampleProject code coverage](https://api.codacy.com/project/badge/Coverage/63aaf7dcbeda43f0b7eb1d70be4ed36b)](https://www.codacy.com/app/tim55667757/ExampleProject/dashboard) [![ExampleProject on PyPI](https://img.shields.io/pypi/v/dohq-example-project.svg)](https://pypi.python.org/pypi/dohq-example-project) [![ExampleProject license](https://img.shields.io/pypi/l/dohq-example-project.svg)](https://github.com/devopshq/ExampleProject/blob/master/LICENSE) 7 | 8 | ***Содержание:*** 9 | - [Введение](#Introduction) 10 | - [Подготовка репозитория](#Preparing-repo) 11 | - [Подготовка документации](#Preparing-doc) 12 | - [Оценка качества кода](#Codacy) 13 | - [Подготовка автоматической сборки в Travis CI](#Travis-CI) 14 | - [Разработка сборочного скрипта setup.py](#Setup) 15 | - [Настройка конфигурации в .travis.yml](#Configuration) 16 | - [Подготовка и настройка репозитория в PyPI](#PyPI) 17 | - [Публикация новости о релизе в Telegram-канале DevOpsHQ](#News) 18 | - [Проверка тестового проекта](#Testing) 19 | 20 | 21 | # Введение 22 | 23 | **ExampleProject** — это пример простого проекта в собществе DevOpsHQ с базовой функциональностью. Документация содержит в себе примеры и рекомендации для самостоятельной организации сборки любого нового проекта в сообществе DevOpsHQ. Сам проект — имеет типовую структуру и сборку в Travis CI. Фактически, достаточно скопировать этот проект и заменить некоторые настройки, руководствуясь комментариями ниже. 24 | 25 | Подготовка любого нового проекта состоит из шагов, представленных на схеме ниже: 26 | 27 | ![How to create new project in DevOpsHQ](DevOpsHQ_new_project.png "How to create new project in DevOpsHQ") 28 | 29 | 30 | # Подготовка репозитория 31 | 32 | 1. Обсудить и согласовать с [Timur Gilmullin](https://github.com/Tim55667757), [Aleksey Burov](https://github.com/orgs/devopshq/people/allburov) или [Alexander Pazdnikov](https://github.com/apazdnikov) выкладку нового проекта в https://github.com/devopshq. После этого будет создан и настроен репозиторий и типовые группы доступа, выданы права owner на проект. 33 | 34 | 2. В настройках проекта (Settings) в разделе Options разрешается подключать только фичу (в разделе Features) Issue. Wikis и Projects в проектах на GitHub в сообществе DevOpsHQ мы не ведём. 35 | 36 | 3. Там же в настройках проекта в разделе Branches выбираем дефолтовую ветку master. 37 | 38 | 4. На вкладке проекта Issues в разделе Labels создаём только две метки: **Error** и **Task**, остальные удаляем. Milestones создавайте на своё усмотрение, например, если у вас планируется крупная фича к разработке, состоящая из множества зависимых тасков. 39 | 40 | 5. Юнит-тесты формата pytest должны располагаться в каталоге **./tests** в корне проекта. 41 | 42 | 6. При инициализации репозитория следует использовать только **MIT-лицензию** под именем **LICENSE** следующего содержания (обновив год): 43 | 44 | ``` 45 | MIT License 46 | 47 | Copyright (c) 2017 Open DevOps Community 48 | 49 | Permission is hereby granted, free of charge, to any person obtaining a copy 50 | of this software and associated documentation files (the "Software"), to deal 51 | in the Software without restriction, including without limitation the rights 52 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 53 | copies of the Software, and to permit persons to whom the Software is 54 | furnished to do so, subject to the following conditions: 55 | 56 | The above copyright notice and this permission notice shall be included in all 57 | copies or substantial portions of the Software. 58 | 59 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 60 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 61 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 62 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 63 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 64 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 65 | SOFTWARE. 66 | ``` 67 | 68 | 69 | ## Подготовка документации 70 | 71 | 1. Документация к проекту на английском языке должна вестись в файле **README.md** формата **markdown**, который должен располагаться в корне репозитория в каждой ветке. Версионирование и изменения в документацию вносятся как в обычный код, вместе с отдельными комитами в соответствующую ветку. Документация на русском ведётся аналогично в файле **README_RUS.md**. 72 | 73 | 2. На вкладке Settings проекта в разделе Options подключаем [GitHub Pages сервис](https://pages.github.com/): 74 | * В качестве Source выбираем master branch. То есть, актуальная документация всегда будет браться для сайта на GitHub Pages из этой ветки. 75 | * В пункте Theme chooser нажимаете кнопку Change theme и выбираете любую понравившуюся тему для сайта с документацией. Обычно в DevOpsHQ мы используем "Hacker theme". 76 | 77 | После этого в ветке master в корне репозитория будет создан файл с настройками для GitHub Pages **_config.yml**. 78 | 79 | 3. Если документация объёмная (больше одной страницы или экрана текста), то рекомендуется добавить в неё содержание со ссылками. 80 | 81 | [Markdown](https://ru.wikipedia.org/wiki/Markdown) (маркдаун) — облегчённый язык разметки, созданный с целью написания максимально читаемого и удобного для правки текста, но пригодного для преобразования в языки для продвинутых публикаций (HTML, Rich Text и др.). 82 | 83 | Для работы с ним есть множество онлайн-инструментов, в том числе с инструкцией по правильной разметке текста, например: 84 | * [Dillinger](http://dillinger.io/) — в этом онлайн-редакторе можно на лету форматировать markdown-файлы и смотреть результат визуализации разметки. 85 | 86 | Также и GitHub поддерживает автоматическое отображение README.md файлов в формате markdown. 87 | 88 | В маркдаун-документацию можно добавлять индекс (оглавление) на внутренние якоря в документе. При этом ссылки в таком оглавлении будут кликабельными, как в обычном html-документе. Это полезно для больших markdown-документов. 89 | 90 | Для того, чтобы сделать оглавление: 91 | 92 | 1. Пишем в оглавлении ссылку вида: 93 | 94 | **\[HEADER\](#anchor_name)** 95 | 96 | 2. Рядом с нужным местом (заголовком) в документе добавляем обычный html-якорь: 97 | 98 | **\\ HEADER** 99 | 100 | Альтернативный вариант: 101 | 102 | 1. Пишем в оглавлении ссылку вида: 103 | 104 | **\[Long Header\](#long-header)** 105 | 106 | 2. В тексте заголовок должен быть такой же, как в квадратных скобках выше: 107 | 108 | **Long Header** 109 | 110 | 111 | ***Дополнительно:*** 112 | 113 | Как реализовать подсветку синтаксиса: https://help.github.com/articles/creating-and-highlighting-code-blocks/ 114 | 115 | Полный список алиасов для языков программирования: https://github.com/github/linguist/blob/master/lib/linguist/languages.yml 116 | 117 | 118 | 119 | ## Оценка качества кода 120 | 121 | Качество кода автоматически отслеживается [сервисом Codacy](https://www.codacy.com/). Для его настройки: 122 | 123 | 1. Авторизуйтесь со своей GitHub-учёткой, или учёткой, созданной в самом сервисе: https://www.codacy.com/ 124 | 125 | 2. Нажмите кнопку Add project. 126 | 127 | 3. Выберете проект из списка или добавьте URL на код в GitHub-е. 128 | 129 | 4. После обработки проекта он появится на дашборде. 130 | 131 | 5. Настройка автоматического подсчёта покрытия кода тестами (Coverage) будет реализована позже в разделе про Travis CI сборки. 132 | 133 | 5. Перейдите в настройки проекта (кнопка settings в меню слева) и скопируйте Codacy Badge для проекта в формате markdown. Это ссылка на оценку качества кода. 134 | 135 | 7. Вставьте ссылку на значок с оценкой качества кода в документацию README.md в самом начале, сразу после заголовка с названием проекта. Она должна иметь вид, похожий на этот: 136 | 137 | \[![code quality\](https://api.codacy.com/project/badge/**Grade/f1511115ad144614915fc5767029e2d9**)\](https://www.codacy.com/app/**tim55667757/FuzzyClassificator**/dashboard) 138 | 139 | Выделенное длинное число — это код значка для проекта в Codacy (можно узнать в настройках Settings - General - Codacy Badge), а выделенная часть ссылки — это ваш логин и имя проекта в Codacy. 140 | 141 | 8. После того, как любая сборка запушит первый раз данные по тестовому покрытию, можно также вставить ссылку на значок с оценкой покрытия кода тестами. Ссылка должна иметь вид, похожий на этот: 142 | 143 | \[![code coverage\](https://api.codacy.com/project/badge/**Coverage/f1511115ad144614915fc5767029e2d9**)\](https://www.codacy.com/app/**tim55667757/FuzzyClassificator**/dashboard) 144 | 145 | Выделенное длинное число — это код проекта в Codacy (его можно узнать в настройках Settings — General — Codacy Badge), а выделенная часть ссылки — это ваш логин и имя проекта в Codacy. 146 | 147 | 148 | # Подготовка автоматической сборки в Travis CI 149 | 150 | Подготовка сборки python-кода в [Travis CI](https://travis-ci.org/devopshq) состоит из нескольких основных шагов: 151 | 152 | * разработки сборочного скрипта **setup.py** (для стандартного сборщика python из библиотеки setuptools), 153 | * настройки конфигурации в **.travis.yml** (стандартный файл конфигурации для Travis CI), 154 | * настройки **репозитория в PyPI**. 155 | 156 | Для начала работы с Travis CI включите интеграцию в вашем GitHub проекте: для этого перейдите в Travis CI по ссылке https://travis-ci.org/profile/devopshq и включите интеграцию вашего нового проекта с GitHub. Для этой операции необходимы админские права в сообществе DevOpsHQ. 157 | 158 | 159 | ## Разработка сборочного скрипта setup.py 160 | 161 | Скрипт **setup.py** используется стандартным сборщиком python из библиотеки setuptools для обеспечения локальной сборки инструмента в пакет. Обычно, для локального билда и установки вашего инструмента в библиотеки локального python используют команду: python setup.py install. Этот же самый принцип использует Travis CI для обеспечения сборки и дальнейшей упаковки пакета, например, в .tar.gz или wheel-файл и загрузки в PyPI. 162 | 163 | Добавьте файлы **setup.py** и **setup.cfg** в корень своего репозитория. А также добавьте пустой файл **\_\_init\_\_.py** в каталог со скриптами, который вы хотите сделать пакетом и который после сборки можно будет импортировать в других проектах. 164 | 165 | В **setup.cfg** достаточно добавить две строчки, с указанием того, где искать документацию: 166 | 167 | [metadata] 168 | description-file = README.md 169 | 170 | Ниже представлен готовый **пример файла setup.py** с минимальным набором настроек для локальной сборки пакета. Внимательно читайте комментарии. Достаточно скопировать его к себе и он должен заработать с небольшими исправлениями: 171 | 172 | ```python 173 | #!/usr/bin/env python 174 | # -*- coding: utf-8 -*- 175 | 176 | 177 | from setuptools import setup 178 | import os 179 | 180 | __version__ = '1.0' # Здесь можно менять глобальный мажор.минор вашего инструмента. Итоговая версия после сборки будет выглядеть так: [major.minor].[build] для релизных сборок и [major.minor.dev]build для нерелизных. 181 | # В дальнейшем узнать версию вашего установленного инструмента внутри программы возможно используя метод, аналогичный этому: 182 | # https://github.com/devopshq/FuzzyClassificator/blob/master/FuzzyClassificator.py#L27 183 | # import pkg_resources # часть стандартной библиотеки setuptools 184 | # version = pkg_resources.get_distribution('YourProject').version 185 | 186 | devStatus = '4 - Beta' # Билд-статус по умолчанию, смотрите: https://pypi.python.org/pypi?%3Aaction=list_classifiers 187 | 188 | # Логика версионирования в зависимости от веток настраивается ниже: 189 | if 'TRAVIS_BUILD_NUMBER' in os.environ and 'TRAVIS_BRANCH' in os.environ: 190 | print("This is TRAVIS-CI build") 191 | print("TRAVIS_BUILD_NUMBER = {}".format(os.environ['TRAVIS_BUILD_NUMBER'])) 192 | print("TRAVIS_BRANCH = {}".format(os.environ['TRAVIS_BRANCH'])) 193 | 194 | __version__ += '.{}{}'.format( 195 | '' if 'release' in os.environ['TRAVIS_BRANCH'] or os.environ['TRAVIS_BRANCH'] == 'master' else 'dev', 196 | os.environ['TRAVIS_BUILD_NUMBER'], 197 | ) 198 | 199 | devStatus = '5 - Production/Stable' if 'release' in os.environ['TRAVIS_BRANCH'] or os.environ['TRAVIS_BRANCH'] == 'master' else devStatus 200 | 201 | else: 202 | print("This is local build") 203 | __version__ += '.dev0' # set version as major.minor.localbuild if local build: python setup.py install 204 | 205 | print("YourProject build version = {}".format(__version__)) # Перед сборкой выведется сообщение о том, какая версия собирается 206 | 207 | # Это основной раздел настроек setuptools для сборки вашей программы 208 | setup( 209 | name='YourProject', # имя проекта под которым люди будут искать вашу программу в PyPI и инсталлить через "pip install YourProject" 210 | 211 | version=__version__, 212 | 213 | description='Short description of your project.', # короткое описание проекта - отображается рядом с пакетом в PyPI 214 | 215 | long_description='You can see detailed user manual here: https://devopshq.github.io/YourProject/', # подробная документация должна быть доступна в GitHub Pages по этой ссылке 216 | 217 | license='MIT', # только MIT лицензия для Open DevOps Community 218 | 219 | author='Open DevOps Community', # укажите имя основного автора, либо укажите Open DevOps Community 220 | 221 | author_email='tim55667757@gmail.com', # е-mail автора либо ссылка на Open DevOps Community 222 | 223 | url='https://devopshq.github.io/YourProject/', # сюда пишем ссылку на GitHub Pages или другой сайт с документацией 224 | 225 | download_url='https://github.com/devopshq/YourProject.git', # здесь указываем ссылку на проект в GitHub 226 | 227 | entry_points={'console_scripts': ['MainScript = MainScript:Main']}, # Точка входа указывает на основной метод, который нужно запустить при запуске программы из консоли. Например, если основной модуль называется MainScript, то в данном примере будет запущен метод Main() этого скрипта, если вы наберёте в консоли команду "MainScript". 228 | 229 | classifiers=[ # все допустимые классификаторы для PyPI подробно перечислены на страничке: https://pypi.python.org/pypi?%3Aaction=list_classifiers 230 | 'Development Status :: {}'.format(devStatus), 231 | 'Environment :: Console', 232 | 'Intended Audience :: Science/Research', 233 | 'Topic :: Scientific/Engineering :: Artificial Intelligence', 234 | 'License :: OSI Approved :: MIT License', 235 | 'Natural Language :: English', 236 | 'Programming Language :: Python :: 3.6', 237 | ], 238 | 239 | keywords=[ # перечислите все ключевые слова, которые ассоциируются с вашим инструментом, каждое слово отдельной записью 240 | 'keyword 1', 241 | 'keyword 2', 242 | ], 243 | 244 | packages=[ # необходимо перечислить ВСЕ каталоги с пакетами, если они присутствуют в вашем проекте, либо оставить '.', что будет указывать на то, что корень проекта сам является пакетом (в корне должен быть __init__.py) 245 | '.', 246 | ], 247 | 248 | setup_requires=[ # необходимо перечислить ВСЕ библиотеки, от которых зависит сборка вашего инструмента 249 | ], 250 | 251 | tests_require=[ # необходимо перечислить ВСЕ библиотеки, которые должны быть установлены для запуска тестов 252 | 'pytest', 253 | ], 254 | 255 | install_requires=[ # необходимо перечислить ВСЕ библиотеки, от которых зависит ваш инструмент (requirements), кроме стандартных библиотек, и они будут установлены автоматически при установке вашего инструмента 256 | ], 257 | 258 | package_data={ # необходимо перечислить ВСЕ файлы, которые должны войти в итоговый пакет, например: 259 | '': [ 260 | './someothermodule/*.py', # если проект содержит другие модули, их и все входящие в них файлы тоже нужно перечислить 261 | 262 | './tests/*.py', # все юнит-тесты, если вы хотите, чтобы люди могли их запускать после установки вашей библиотеки 263 | 'MainScript.py', # основной скрипт вашего приложения и все остальные файлы должны быть указаны аналогично 264 | 265 | 'LICENSE', # файл лицензии нужно добавить в пакет 266 | 'README.md', # файл документации нужно добавить в пакет 267 | ], 268 | }, 269 | 270 | zip_safe=True, 271 | ) 272 | ``` 273 | 274 | После разработки скрипта зарегистрируйте новый проект в PyPI (учётку devopshq могут использовать админы сообщества): 275 | 276 | python setup.py register -r pypi 277 | 278 | ***Дополнение:*** *похоже, что это уже не требуется, т.к. PyPI выдаёт на попытку зарегистрировать проект: Server response (410): Project pre-registration is no longer required or supported, so continue directly to uploading files.* 279 | 280 | 281 | ## Настройка конфигурации в .travis.yml 282 | 283 | Travis CI сервис ищет конфигурацию шагов сборки в стандартном файле **.travis.yml**. Описание его разделов подробно описано в родной документации: https://docs.travis-ci.com/user/customizing-the-build. 284 | 285 | 1. Добавьте файл **.travis.yml** в корень репозитория. 286 | 287 | 2. В конфигурационном файле используются учётные данные. Их потребуется зашифровать при помощи утилиты **[travis-encrypt](https://pypi.python.org/pypi/travis-encrypt)**. Установите её для вашего python: 288 | 289 | 290 | pip install travis-encrypt 291 | 292 | 3. Сгенерируйте секретку для деплойного ключа для загрузки артефакта сборки вашего проекта в PyPI командой ниже (потребуется учётка админов devopshq). Длинную строку секретки нужно будет подставить в файл **.travis.yml** в разделе deploy (смотри в примере ниже). 293 | 294 | 295 | travis-encrypt devopshq [имя репозитория проекта в GitHub, например, crosspm] 296 | 297 | 4. Добавьте интеграцию с сервисом Codacy: 298 | * Перейдите в настройки проекта в Codacy: Settings — Integrations, нажмите "Add integrations" и выберете "Project API". 299 | * В добавленной интеграции будет строка "Project API Token" с токеном проекта в Codacy. 300 | 301 | 5. Сгенерируйте секретку для авторизации в сервисе Codacy командой ниже. После ввода команды вы увидите длинную зашифрованную строку секретки. Эту строку нужно будет подставить в файл **.travis.yml** в разделе env (смотри в примере ниже). 302 | 303 | 304 | travis-encrypt --env --password CODACY_PROJECT_TOKEN=[длинное число с токеном проекта в Codacy] devopshq [имя репозитория проекта в GitHub, например, crosspm] 305 | 306 | Ниже представлен пример файла конфигурации **.travis.yml** с минимальным набором типичных шагов сборки в Travis CI для небольших и простых проектов. Достаточно скопировать его к себе, добавить юнит-тесты в ./tests, заменить ключи secure и он должен подойти, либо с минимальными доработками: 307 | 308 | ```YAML 309 | language: python 310 | python: '3.6' 311 | branches: 312 | only: # можно перечислить ветки из которых должен быть автоматический запуск сборки на каждый push кода в репозиторий 313 | - master 314 | - develop 315 | install: # раздел предварительной настройки окружения до сборки 316 | - pip install pytest coverage codacy-coverage # эти библиотеки используются для запуска юнит-тестов сбора статистики покрытия кода юнит-тестами для сервиса Codacy 317 | script: # основной шаг сборки, состоящий из последовательного запуска скриптов 318 | - printenv # для отладки очень помогает вывод переменных окружения в логах Travis CI, потом этот шаг можно удалить 319 | - ls -la # также для отладки, потом этот шаг можно удалить 320 | - coverage run -m py.test tests # собираем покрытие кода тестами 321 | - coverage xml # формируем отчёт для Codacy 322 | - if [[ ! $CODACY_PROJECT_TOKEN ]]; then echo "Variable CODACY_PROJECT_TOKEN not set. Step is skipped."; exit 0; else python-codacy-coverage -r coverage.xml; fi # аплоадим отчёт в Codacy 323 | deploy: # раздел деплоя в котором можно указать действия, которые нужно произвести с успешно собранным артефактом 324 | provider: pypi # например, Travis CI поддерживает автоматическую загрузку в PyPI через указание провайдера "pypi" 325 | user: devopshq # логин проекта в PyPI 326 | password: # зашифрованный пароль для PyPI через утилиту travis-encrypt 327 | secure: "скопируйте сюда длинную зашифрованную строку с паролем для PyPI, полученную через утилиту travis-encrypt" 328 | distributions: sdist bdist_wheel # виды артефактов, которые нужно загрузить в PyPY, sdist загружает .tar.gz, bdist_wheel - загружает wheel-файл 329 | on: 330 | all_branches: true 331 | skip_cleanup: true 332 | after_script: # команды которые нужно выполнить после успешного окончания сборки и деплоя 333 | - echo "Deploy to PyPI finished." 334 | env: 335 | global: # здесь можно разместить общие переменные и секреты доступные для всех шагов сборки, например, секрет для Codacy, зашифрованный через утилиту travis-encrypt 336 | - secure: "скопируйте сюда длинную зашифрованную строку с секретом для Codacy, полученную через утилиту travis-encrypt" 337 | ``` 338 | 339 | 340 | ## Подготовка и настройка репозитория в PyPI 341 | 342 | После того, как в репозиторий был добавлен файл **.travis.yml** и включена интеграция с ним в Travis CI: 343 | 344 | 1. Логинимся в PyPI с учёткой devopshq (доступ к ней у админов DevOpsHQ): https://pypi.python.org 345 | 346 | 2. Справа в меню ищем ранее зарегистрированный проект, кликаем на его имя и на открывшейся странице кликаем на меню roles этого проекта. 347 | 348 | 3. Для Package Name вашего нового проекта небходимо добавить минимальную роль **Maintainer** для пользователя **devopshq**, чтобы Travis CI мог аплоадить артефакты в PyPI-репозиторий. 349 | 350 | 351 | # Публикация новости о релизе в Telegram-канале DevOpsHQ 352 | 353 | Канал сообщества: https://t.me/devopshq. Для публикации в него новости о новой фича или релизной сборке существует чат-бот @devops_mega_bot. Отправлять в канал новости могут админы сообщества DevOpsHQ: 354 | 355 | 1. Обратитесь к [Alexander Kovalev](https://github.com/alkovpro), чтобы он добавил боту опции для работы с новым инструментом. 356 | 357 | 2. После этого в любом чате Telegram станет доступна команда, которая выдаст последнюю версию собранного инструмента в PyPI: 358 | 359 | 360 | @devops_mega_bot [название вашего инструмента] 361 | 362 | 3. После этого можно в канале сообщества опубликовать запись о новой версии и добавить информацию в произвольном виде: что вошло в новую сборку, какие фичи добавлены, какие баги исправлены и т.п. 363 | 364 | 365 | # Проверка тестового проекта 366 | 367 | Чтобы убедиться, что данный тестовый проект **ExampleProject** работает, попробуйте установить его из PyPI: 368 | 369 | pip install dohq-example-project [--upgrade] [--pre] 370 | 371 | В случае успеха установки вы увидите что-то вроде: 372 | 373 | ```Shell 374 | pip install dohq-example-project --upgrade 375 | 376 | Collecting dohq-example-project 377 | Downloading dohq_example_project-1.0.11-py3-none-any.whl 378 | Installing collected packages: dohq-example-project 379 | Found existing installation: dohq-example-project 1.0.dev3 380 | Uninstalling dohq-example-project-1.0.dev3: 381 | Successfully uninstalled dohq-example-project-1.0.dev3 382 | Successfully installed dohq-example-project-1.0.11 383 | ``` 384 | 385 | Запустите тестовый проект: 386 | 387 | exampleproject 388 | 389 | или 390 | 391 | [python_directory]/Scripts/exampleproject 392 | 393 | и вы должны увидеть что-то вроде: 394 | 395 | ```Shell 396 | This is Main module for ExampleProject that do nothing. 397 | Read more about DevOpsHQ Community here: https://github.com/devopshq/ExampleProject 398 | Version of ExampleProject is [ 1.0.11 ] 399 | ``` 400 | 401 | Также можно проверить информацию в pip: 402 | 403 | pip show dohq-example-project 404 | 405 | после чего вы должны увидеть что-то вроде: 406 | 407 | ```Shell 408 | Name: dohq-example-project 409 | Version: 1.0.11 410 | Summary: About Example Project: https://github.com/devopshq/ExampleProject 411 | Home-page: https://devopshq.github.io/ExampleProject/ 412 | Author: Open DevOps Community 413 | Author-email: tim55667757@gmail.com 414 | License: MIT 415 | Location: c:\anaconda3\lib\site-packages 416 | Requires: 417 | ``` 418 | 419 | Аналогично вы можете проверить установку вашего проекта, сделанного на основе данного шаблона. -------------------------------------------------------------------------------- /README_EN.md: -------------------------------------------------------------------------------- 1 | ExampleProject 2 | ============== 3 | This is simple example of project in DevOpsHQ Community with basic functionality. 4 | See full russian instruction here: https://github.com/devopshq/ExampleProject/blob/master/README.md 5 | 6 | [![ExampleProject build status](https://travis-ci.org/devopshq/ExampleProject.svg)](https://travis-ci.org/devopshq/ExampleProject) [![ExampleProject code quality](https://api.codacy.com/project/badge/Grade/63aaf7dcbeda43f0b7eb1d70be4ed36b)](https://www.codacy.com/app/tim55667757/ExampleProject/dashboard) [![ExampleProject code coverage](https://api.codacy.com/project/badge/Coverage/63aaf7dcbeda43f0b7eb1d70be4ed36b)](https://www.codacy.com/app/tim55667757/ExampleProject/dashboard) [![ExampleProject on PyPI](https://img.shields.io/pypi/v/dohq-example-project.svg)](https://pypi.python.org/pypi/dohq-example-project) [![ExampleProject license](https://img.shields.io/pypi/l/dohq-example-project.svg)](https://github.com/devopshq/ExampleProject/blob/master/LICENSE) 7 | 8 | 9 | ***... Soon there will be a translation of the Russian instruction ...*** -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /exampleproject/Main.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | # This is Main module for ExampleProject that do nosting. 5 | 6 | 7 | def Main(): 8 | """ 9 | This is Main method that do nosting. 10 | """ 11 | return "This is Main module for ExampleProject that do nothing.\nRead more about DevOpsHQ Community here: https://github.com/devopshq/ExampleProject" 12 | 13 | 14 | if __name__ == "__main__": 15 | print(Main()) 16 | 17 | import pkg_resources # part of standart setuptools 18 | print("Version of ExampleProject is [ {} ]".format(pkg_resources.get_distribution('dohq-example-project').version)) 19 | -------------------------------------------------------------------------------- /exampleproject/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devopshq/ExampleProject/de6db39c1695d1e8e8eaec5eff019c3c69430912/exampleproject/__init__.py -------------------------------------------------------------------------------- /exampleproject/__main__.py: -------------------------------------------------------------------------------- 1 | from exampleproject.Main import Main 2 | 3 | if __name__ == "__main__": 4 | print(Main()) 5 | 6 | import pkg_resources # part of standart setuptools 7 | print("Version of ExampleProject is [ {} ]".format(pkg_resources.get_distribution('dohq-example-project').version)) 8 | 9 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md 3 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | from setuptools import setup 6 | import os 7 | 8 | __version__ = '1.0' # Здесь можно менять глобальный мажор.минор вашего инструмента. Итоговая версия после сборки будет выглядеть так: [major.minor].[build] для релизных сборок и [major.minor.dev]build для нерелизных. 9 | # В дальнейшем узнать версию вашего установленного инструмента внутри программы возможно используя метод, аналогичный этому: 10 | # https://github.com/devopshq/FuzzyClassificator/blob/master/FuzzyClassificator.py#L27 11 | # import pkg_resources # часть стандартной библиотеки setuptools 12 | # version = pkg_resources.get_distribution('YourProject').version 13 | 14 | devStatus = '4 - Beta' # Билд-статус по умолчанию, смотрите: https://pypi.python.org/pypi?%3Aaction=list_classifiers 15 | 16 | # Логика версионирования в зависимости от веток настраивается ниже: 17 | if 'TRAVIS_BUILD_NUMBER' in os.environ and 'TRAVIS_BRANCH' in os.environ: 18 | print("This is TRAVIS-CI build") 19 | print("TRAVIS_BUILD_NUMBER = {}".format(os.environ['TRAVIS_BUILD_NUMBER'])) 20 | print("TRAVIS_BRANCH = {}".format(os.environ['TRAVIS_BRANCH'])) 21 | 22 | __version__ += '.{}{}'.format( 23 | '' if 'release' in os.environ['TRAVIS_BRANCH'] or os.environ['TRAVIS_BRANCH'] == 'master' else 'dev', 24 | os.environ['TRAVIS_BUILD_NUMBER'], 25 | ) 26 | 27 | devStatus = '5 - Production/Stable' if 'release' in os.environ['TRAVIS_BRANCH'] or os.environ['TRAVIS_BRANCH'] == 'master' else devStatus 28 | 29 | else: 30 | print("This is local build") 31 | __version__ += '.dev0' # set version as major.minor.localbuild if local build: python setup.py install 32 | 33 | print("ExampleProject build version = {}".format(__version__)) # Перед сборкой выведется сообщение о том, какая версия собирается 34 | 35 | # Это основной раздел настроек setuptools для сборки вашей программы 36 | setup( 37 | name='dohq-example-project', # имя проекта под которым люди будут искать вашу программу в PyPI и инсталлить через "pip install dohq-example-project" 38 | 39 | version=__version__, 40 | 41 | description='About Example Project: https://github.com/devopshq/ExampleProject', # короткое описание проекта - отображается рядом с пакетом в PyPI 42 | 43 | long_description='GitHub Pages: https://devopshq.github.io/ExampleProject/', # подробная документация должна быть доступна в GitHub Pages по этой ссылке 44 | 45 | license='MIT', # только MIT лицензия для Open DevOps Community 46 | 47 | author='Open DevOps Community', # укажите имя основного автора, либо укажите Open DevOps Community 48 | 49 | author_email='tim55667757@gmail.com', # е-mail автора либо ссылка на Open DevOps Community 50 | 51 | url='https://devopshq.github.io/ExampleProject/', # сюда пишем ссылку на GitHub Pages или другой сайт с документацией 52 | 53 | download_url='https://github.com/devopshq/ExampleProject.git', # здесь указываем ссылку на проект в GitHub 54 | 55 | entry_points={'console_scripts': ['exampleproject = exampleproject.Main:Main']}, # Точка входа указывает на основной метод, который нужно запустить при запуске программы из консоли. Например, если основной модуль в пакете exampleproject называется Main, то в данном примере будет запущен метод Main() этого скрипта, если вы наберёте в консоли команду "exampleproject". 56 | 57 | classifiers=[ # все допустимые классификаторы для PyPI подробно перечислены на страничке: https://pypi.python.org/pypi?%3Aaction=list_classifiers 58 | 'Development Status :: {}'.format(devStatus), 59 | 'Environment :: Console', 60 | 'Intended Audience :: Developers', 61 | 'Topic :: Utilities', 62 | 'License :: OSI Approved :: MIT License', 63 | 'Natural Language :: Russian', 64 | 'Programming Language :: Python :: 3.6', 65 | ], 66 | 67 | keywords=[ # перечислите все ключевые слова, которые ассоциируются с вашим инструментом, каждое слово отдельной записью 68 | 'exampleproject', 69 | 'PyPI', 70 | 'DevOpsHQ', 71 | 'devops', 72 | ], 73 | 74 | packages=[ # необходимо перечислить ВСЕ каталоги с пакетами, если они присутствуют в вашем проекте, либо оставить '.', что будет указывать на то, что корень проекта сам является пакетом (в корне должен быть __init__.py) 75 | 'exampleproject', 76 | ], 77 | 78 | setup_requires=[ # необходимо перечислить ВСЕ библиотеки, от которых зависит сборка вашего инструмента 79 | ], 80 | 81 | tests_require=[ # необходимо перечислить ВСЕ библиотеки, которые должны быть установлены для запуска тестов 82 | 'pytest', 83 | ], 84 | 85 | install_requires=[ # необходимо перечислить ВСЕ библиотеки, от которых зависит ваш инструмент (requirements), кроме стандартных библиотек, и они будут установлены автоматически при установке вашего инструмента 86 | ], 87 | 88 | package_data={ # необходимо перечислить ВСЕ файлы, которые должны войти в итоговый пакет, например: 89 | '': [ 90 | './exampleproject/*.py', # если проект содержит другие модули, их и все входящие в них файлы тоже нужно перечислить 91 | 92 | './tests/*.py', # все юнит-тесты, если вы хотите, чтобы люди могли их запускать после установки вашей библиотеки 93 | 94 | 'LICENSE', # файл лицензии нужно добавить в пакет 95 | 'README.md', # файл документации нужно добавить в пакет 96 | 'README_EN.md', # файл документации на английском нужно также добавить в пакет 97 | ], 98 | }, 99 | 100 | zip_safe=True, 101 | ) 102 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/devopshq/ExampleProject/de6db39c1695d1e8e8eaec5eff019c3c69430912/tests/__init__.py -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | def pytest_sessionstart(session): 5 | 6 | print("This is pre-test part example.") 7 | -------------------------------------------------------------------------------- /tests/test_Main.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | import pytest 5 | from exampleproject import Main 6 | 7 | 8 | class TestMain(): 9 | 10 | @pytest.fixture(scope='class', autouse=True) 11 | def init(self): 12 | print("This is start of test example.") 13 | 14 | def test_Main(self): 15 | assert Main.Main() == "This is Main module for ExampleProject that do nothing.\nRead more about DevOpsHQ Community here: https://github.com/devopshq/ExampleProject" 16 | --------------------------------------------------------------------------------