По вашему запросу ничего не найдено :(
Убедитесь, что запрос написан правильно, или посмотрите другие наши статьи:
img
Привет всем! В сегодняшней статье мы хотим рассказать об одном крайне полезном трюке, который поможет сохранить время Вам и клиентам, позвонившим в Вашу компанию. Демонстрировать этот функционал мы будем на IP-АТС Asterisk через графический интерфейс FreePBX 14. Данная статья будет особенно актуальна для тех, кто пользуется переадресацией входящих звонков на мобильный телефон. Возможно, кто-то уже использует данный способ, но многие могут о нем и не знать. Кейс Итак, представим себе такую гипотетическую ситуацию: К нам в компанию позвонил клиент; Звонок поступил на ринг группу 345, в которой находится 3 внутренних номера; Звонки с этих внутренних номеров переадресовываются на мобильные номера менеджеров; И вот на своём мобильном телефоне звонок клиента принял менеджер Алексей; Они общаются, и тут у клиента возникает вопрос к инженеру, клиент просит перевести его на инженера; Алексей может находиться вне офиса и не за стационарным телефоном и не может перевести звонок клиента обратно; Он просит клиента перезвонить на общий номер компании и донабрать внутренний номер инженера; Ситуация вполне нормальная, но мы вынуждены просить нашего клиента звонить повторно, донабирать номер, тратить свое время и так далее. Вот бы было здорово иметь возможность перевести звонок клиента на нужный номер прямо с мобильного? А ещё лучше, если мы сможем поговорить с человеком, на которого нужно перевести звонок и узнать не занят ли он, прежде чем делать трансфер! Такая возможность есть и сейчас мы объясним как её реализовать. Решение Дело в том, что когда звонки с нашей IP-АТС переводятся на мобильный телефон, то канал между ними не разрывается. Например, если у вас включена запись, то вы можете увидеть, что такие звонки также записываются. А значит, мы можем контролировать такие звонки на любом устройстве, даже на мобильном телефоне. Делать трансфер, ставить на ожидание, парковать и так далее. Для того, чтобы открылась возможность сделать трансфер на другой номер, находясь в звонке, нужно передать приложению Asterisk Dial() нужный аргумент. Во FreePBX это настраивается в Settings → Advanced Settings в разделе Dialplan and Operational. Здесь есть два поля - Asterisk Dial Options, в котором можно добавить аргументы Dial() при совершении внутренних звонков и Asterisk Outbound Trunk Dial Options, который отвечает за обработку аргументов Dial() при совершении внешних звонков через транк, как раз это поле нам и нужно. По умолчанию в данном поле всего один аргумент - большая буква T. Этот аргумент позволяет позвонившей стороне сделать трансфер используя feature code - ## Сервисный код ## соответствует функции “слепого” трансфера -In-Call Asterisk Blind Transfer Однако, когда мы принимаем звонок на мобильном телефоне, то являемся вызываемой стороной, поэтому нам нужен другой аргумент – маленькая буква t. С помощью данного аргумента, мы сможем делать трансфер находясь в звонке, используя всё тот же feature code - ##. Итак, можно добавить аргумент t в поле Asterisk Outbound Trunk Dial Options, но тогда этот функционал распространится на все транки, которые созданы на вашей IP-АТС. Есть более безопасный способ включить трансфер на принимающей стороне. Для этого переходим в Connectivity → Trunks и в настройках транка на вкладке General ищем опцию Asterisk Trunk Dial Options По умолчанию, в данной опции мы так же увидим аргумент T, так как стоит параметр System, который просто подтягивает значения аргумента из Asterisk Outbound Trunk Dial Options в Advanced Settings Выбрав параметр Override, мы можем записать сюда какие угодно аргументы и они будут действовать только для данного конкретного транка. Запишем сюда маленькую t. Итак, теперь, если Вы приняли вызов на мобильном телефоне, а человек, с которым Вы разговариваете просит перевести его на другого сотрудника, Вы можете просто: Нажать ## на своём мобильном телефоне, после чего Вы услышите в трубке сообщение “перевод”; Набрать нужный номер (например - 529). В это время позвонивший будет слышать музыку на ожидании; Вызов автоматически завершится, а звонок будет переадресован тому, чей номер Вы набрали; Profit; А помните мы говорили, что можно ещё поговорить с тем, кому нужно перевести вызов, прежде чем его переводить, чтобы уточнить не занят ли этот человек? Так вот такая возможность при принятии звонка на мобильном тоже есть! Если мы откроем возможные сервисные коды (feature code) функций трансфера, то увидим, что их два - ## - In-Call Asterisk Blind Transfer, который мы уже знаем, и *2 - функция консультативного трансфера - In-Call Asterisk Attended Transfer. Таким образом, можно также пользоваться консультативным трансфером, в этом случае нужно: Нажать *2 на своём мобильном телефоне, после чего Вы услышите в трубке сообщение “перевод”; Набрать нужный номер (например - 529). В это время позвонивший будет слышать музыку на ожидании; Дождаться, пока человек, которому нужно перевести вызов, ответит и узнать у него можно ли делать перевод. Если он сбросит или не возьмёт трубку, то ваш разговор с ожидающим на линии абонентом возобновится и Вы сможете объяснить ему, что соединиться не удалось; Если человек, которому нужно перевести вызов готов поговорить с ожидающим на линии абонентом, то нужно просто завершить вызов. Тогда разговор продолжится уже между ними; Кстати! Номер, который Вы набираете после того или иного сервисного кода, не обязательно должен быть внутренним. Это может быть любой другой номер (например, мобильный - *289012345678). Главное набирать его в таком формате, чтобы Ваша IP-АТС могла до него дозвониться.
img
Начиная своё знакомство с iptables, следует рассказать про netfilter. Netfilter - это набор программных хуков внутри ядра Linux, которые позволяют модулям ядра регистрировать функции обратного вызова от стека сетевых протоколов. Хук (hook) - это программный элемент, который позволяет перехватывать функции обратного вызова в чужих процессах. Netfilter является основой для построения Firewall'а в дистрибутивах Linux, но для того, чтобы он заработал в полную силу его нужно настроить. Как раз с помощью iptables мы можем взаимодействовать с хуками Netfilter и создавать правила фильтрации, маршрутизации, изменения и транслирования пакетов. Иногда про Netfilter забывают и называют эту связку просто iptables. Введение Итак, iptables - это утилита для настройки программного Firewall'а (межсетевого экрана) linux, которая предустанавливается по умолчанию во все сборки Linux, начиная с версии 2.4. Запускается iptables из командной строки (CLI) под пользователем с правами root и настраивается там же. Можете в этом убедиться, набрав команду iptables -V в командной строке, она покажет вам версию iptables. Почему же iptables всем так понравился, что его стали включать во все сборки Linux? Всё дело в том, что iptables действительно очень прост в настройке. С помощью него можно решить следующие задачи: Настроить stateless и statefull фильтрацию пакетов версий IPv4 и IPv6; Stateless - это фильтрация, основанная на проверке статических параметров одного пакета, например: IP адрес источника и получателя, порт и другие не изменяющиеся параметры. Statefull - это фильтрация, основанная на анализе потоков трафика. С помощью нее можно определить параметры целой TCP сессии или UDP потока. Настраивать все виды трансляции IP адресов и портов NAT, PAT, NAPT; Настроить политики QoS; Производить различные манипуляции с пакетами, например - изменять поля в заголовке IP. Прежде чем переходить к практике, давайте обратимся к теории и поймём саму логику iptables. Логика и основные понятия iptables Правила Как и все файрволлы, iptables оперирует некими правилами (rules), на основании которых решается судьба пакета, который поступил на интерфейс сетевого устройства (роутера). Ну допустим у нас есть сетевое устройство с адресом 192.168.1.1, на котором мы настроили iptables таким образом, чтобы запрещать любые ssh (порт 22) соединения на данный адрес. Если есть пакет, который идёт, например, с адреса 192.168.1.15 на адрес 192.168.1.1 и порт 22, то iptables скажет: “Э, нет, брат, тебе сюда нельзя” и выбросит пакет. Или вообще ничего не скажет и выбросит, но об этом чуть позже :) Каждое правило в iptables состоит из критерия, действия и счётчика Критерий - это условие, под которое должны подпадать параметры пакета или текущее соединение, чтобы сработало действие. В нашем примере – этим условием является наличие пакета на входящем интерфейсе, устанавливающего соединение на порт 22 Действие - операция, которую нужно проделать с пакетом или соединением в случае выполнения условий критерия. В нашем случае – запретить пакет на порт 22 Счетчик - сущность, которая считает сколько пакетов было подвержено действию правила и на основании этого, показывает их объём в байтах. Цепочки Набор правил формируется в цепочки (chains) Существуют базовые и пользовательские цепочки. Базовые цепочки - это набор предустановленных правил, которые есть в iptables по умолчанию. Существует 5 базовых цепочек и различаются они в зависимости от того, какое назначение имеет пакет. Имена базовых цепочек записываются в верхнем регистре. PREROUTING - правила в этой цепочке применяются ко всем пакетам, которые поступают на сетевой интерфейс извне; INPUT - применяются к пакетам, которые предназначаются для самого хоста или для локального процесса, запущенного на данном хосте. То есть не являются транзитными; FORWARD - правила, которые применяются к транзитным пакетам, проходящими через хост, не задерживаясь; OUTPUT - применяются к пакетам, которые сгенерированы самим хостом; POSTROUTING - применяются к пакетам, которые должны покинуть сетевой интерфейс. В базовых цепочках обязательно устанавливается политика по умолчанию, как правило – принимать (ACCEPT) или сбрасывать (DROP) пакеты. Действует она только в цепочках INPUT, FORWARD и OUTPUT Таблица Таблицы - это набор базовых и пользовательских цепочек. В зависимости от того, в какой таблице находится цепочка правил, с пакетом или соединением производятся определённые действия Существует 5 таблиц: filter - таблица, выполняющая функции фильтрации пакетов по определённым параметрам. В большинстве случаев вы будете использовать именно её. Содержит следующие встроенные цепочки: FORWARD, INPUT, OUTPUT; raw - чтобы понять предназначение этой таблицы, нужно понимать логику работы statefull firewall'а. Дело в том, что по умолчанию, iptables рассматривает каждый пакет как часть большого потока и может определить какому соединению принадлежит тот или иной пакет. С помощью raw таблицы настраиваются исключения, которые будут рассматривать пакет как отдельную, ни к чему не привязанную сущность. Содержит следующие встроенные цепочки: INPUT, OUTPUT; nat - таблица, предназначенная целиком по функции трансляции сетевых адресов. Содержит следующие встроенные цепочки: PREROUTING, OUTPUT, POSTROUTING; mangle - таблица, предназначенная для изменения различных заголовков пакета. Можно, например, изменить TTL, количество hop'ов и другое. Содержит следующие встроенные цепочки: PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING>; security - используется для назначения пакетам или соединениям неких меток, которые в дальнейшем может интерпретировать SElinux. Теперь мы можем представить себе логику iptables в виде следующей схемы: Действия Ну и последнее, о чем нужно рассказать, прежде чем мы с вами начнем писать правила - это target. В контексте iptables, target - это действие, которое нужно проделать с пакетом или соединением, которое совпало с критериями правила. Итак, наиболее используемые действия: ACCEPT - разрешить прохождение пакета; DROP - тихо выбросить пакет, не сообщая причин; QUEUE - отправляет пакет за пределы логики iptables, в стороннее приложение. Это может понадобиться, когда нужно обработать пакет в рамках другого процесса в другой программе; RETURN - остановить обработку правила и вернуться на одно правило назад. Это действие подобно break'у в языке программирования. Помимо этих четырех, есть ещё масса других действий, которые называются расширенными (extension modules): REJECT - выбрасывает пакет и возвращает причину в виде ошибки, например: icmp unreachable; LOG - просто делает запись в логе, если пакет соответствует критериям правила; Есть действия, которые доступны только в определенной цепочке и таблицах, например, только в табоице nat и цепочках OUTPUT и PREROUTING доступно действие DNAT, которое используется в NAT'ировании и меняет Destination IP пакета. В той же таблице, только в цепочке POSTRUNNING доступно действие SNAT, меняющее Source IP пакета. Отдельно остановимся на действии MASQUERADE, которое делает то же самое что SNAT, только применяется на выходном интерфейсе, когда IP адрес может меняться, например, когда назначается по DHCP. Пишем правила Отлично, теперь давайте приближаться к практике. Как Вы уже поняли, мы будем писать правила, поэтому нам нужно понять, как они строятся. Итак, допустим у нас есть хост с адресом 192.168.2.17, на 80 (http) порту которого, работает вэб-сервер Apache. Мы заходим на адрес http://192.168.2.17 с хоста с адресом 192.168.2.2 и всё отлично работает: А теперь открываем командную строку под root на хосте 192.168.2.17 и пишем: iptables -A INPUT -p tcp -s 192.168.2.2 --dport 80 -j DROP Попробуем открыть открыть http://192.168.2.17 ещё раз: Упс, не работает. Давайте теперь разбираться, что мы наделали? Всё очень просто – данной командой мы: вызвали утилиту iptables; -A - этим ключом мы указали, что нужно добавить правило к существующей цепочке; INPUT - указали цепочку, к которой хотим добавить правило; -p tcp - явно указали протокол TCP. Здесь также можно указывать другие протоколы (udp, icmp, sctp), или номер протокола, инкапсулируемого в IP (17 – udp, 6 – tcp и др.); -s 192.168.2.2 - указали, какой адрес источника должен быть у пакета, который мы хотим фильтровать; --dport 80 - указали адресованные какому порту пакеты мы хотим фильтровать. В данном случае - 80, на котором работает наш сервер Apache. -j DROP - указали что нужно сделать с пакетом, параметры которого совпали с данными критериями. В данном случае – просто тихо выбросить. Таким образом, мы заблокировали все пакеты с адреса 192.168.2.2 на локальный порт 80 и тем самым закрыли доступ к нашему серверу Apache для данного хоста. Обратите внимание – мы не указывали таблицу, в цепочки которой мы хотим добавить правило. Поэтому, по умолчанию таблица - filter. Для явного указания таблицы нужно перед указанием цепочки ввести ключ -t или (--table) Чтобы открыть доступ опять просто поменяем ключ -A в правиле на -D, тем самым мы удалим данное правило из iptables. Синтаксис iptables Друзья, на самом деле в iptables очень богатый синтаксис правил. Полный список ключей и параметров вы можете найти в официальном гайде на iptables.org. Мы же приведём самые “ходовые” опции, которыми вы, вероятно, будете пользоваться. Чтобы вы не запутались, мы приводим их в табличках ниже. Для удобства, в iptables реализовано очень много сокращений для разных ключей. Например, мы писали ключ -A вместо полного --append, -p вместо полного --proto и -s вместо полного --source, дальше мы покажем, что ещё можно сократить и где применить. Начнём с команд для редактирования правил и цепочек – добавления, удаления, замены и так далее: коротко синтаксис правила применение -A --append {цепочка правила} добавить правило к цепочке (в самое начало) -D --delete {цепочка правила} удалить правило из цепочки -D --delete {номер правила в цепочке} удалить правило из цепочки по номеру (1 - x) -I --insert {номер правила вцепочке} вставить правило в цепочку по номеру (1 - x) -R --replace {номер правила вцепочке} заменить правило в цепочке по номеру (1 - x) -X --delete-chain {цепочка} удалить цепочку (только для пользовательских) -E --rename-chain {старое имя цепочки} {новое имя цепочки} переименовать цепочку -N --new {имя цепочки} создание новой пользовательской цепочки -C --check {правило цепочки} проверит наличие правила в цепочке -F --flush {цепочка} удаляет все правила в цепочке, если цепочка не указана – удалятся все правила -Z --zero {цепочка} {номер правила вцепочке} обнуляет все счётчики пакетов и байтов в цепочке или всех цепочках -P --policy {цепочка} {номер правила вцепочке} изменяет политику по умолчанию, она должна основываться на встроенном target’e {ACCEPT, DROP, QUEUE} Продолжим синтаксисом настройки правил – на каком сетевом интерфейсе следить за пакетами, какой протокол проверять, адрес источника, назначения и так далее. Кстати, перед некоторыми параметрами можно ставить восклицательный знак - !, означающее логическое НЕ. В таблице мы пометим такие параметры таким значком – (!) коротко синтаксис опции применение -p (!) --proto {протокол} протокол {tcp, udp, udplite, icmp, esp, ah, sctp} или номер протокола {16,7}, all - все протоколы -4 --ipv4 указывает версию протокола ipv4 -6 --ipv6 указывает версию протокола ipv6 -s (!) --source {адрес/маска} указывает ip адрес источника -d (!) --destination {адрес/маска} указывает ip адрес назначения -m --match включает дополнительные модули, явно задающимися данным ключем. например <code>m limit --limit 3/min</code> - установит лимит на количество пакетов в минуту -f (!) --fragment включает обработку фрагментированных пакетов, в которых нет параметров изначального полного пакета, содержащихся в первом фрагменте пакета -i (!) --in-interface {имя интерфейса} обрабатывает только входящие пакеты, прилетающие на сетевой интерфейс {имя интерфейса} -o (!) --out-interface {имя интерфейса} обрабатывает только исходящие пакеты, прилетающие на сетевой интерфейс {имя интерфейса} --set-counters {пакеты} {байты} включает счётчик для ключей--insert, --append, --replace Теперь рассмотрим опции для действий, которые должны сработать по совпадению критериев: коротко синтаксис опции применение -j --jump {действие} применяет одно из действий accept, drop, reject и другие -g --goto {цепочка} переходит к другой цепочке правил Теперь рассмотрим какую информацию мы можем вытянуть с помощью iptables и какие опции для этого нужно использовать: коротко синтаксис команды применение -l --list {цепочка} {номер правила} показывает правила в цепочке или всех цепочках. по умолчанию покажет таблицу filter -s --list-rules{цепочка} {номер правила} показывает текст правила в цепочке или всех цепочках -n --numeric покажет параметры правила в числовом виде. например не порт будет не http, а 80 -v --verbose выводит более подробную информацию -v --version покажет версию iptables -x --exact покажет точные значения числовых параметров --line-numbers покажет номера правил Для быстрого получения информации о настроенных правилах и о метриках их срабатывания, часто применяется команда, комбинирующая 3 ключа - iptables -nLv. Например, для настроенного нами ранее правила – вывод будет такой: Пример посложнее Давайте рассмотрим ещё один пример. Допустим у нас во локальной сети есть хост 192.168.2.19 с сервером Apache. Мы хотим сделать его доступным из Интернета. Для этого нам нужно воспользоваться возможностями таблицы nat и написать правило, которое будет перенаправлять входящий http трафик на внешний интерфейс (пусть будет enp0s3 с адресом 101.12.13.14) и порт 80 на адрес нашего сервера внутри сети и 80 порт – 192.168.2.19:80. По сути – нужно сделать проброс портов. Напишем такое правило: iptables -t nat -A PREROUTING -i enp0s3 -p tcp --dport 80 -j DNAT --to 192.168.2.19:80 Теперь если мы перейдём по адресу http://101.12.13.14, то должны попасть на наш Apache. Возможности iptables настолько обширны, что мы могли бы начать писать новую Базу знаний по нему. В статье мы показали лишь базовые варианты применения. Это действительно великий инструмент и освоить его не так уж сложно. Надеюсь, данная статья Вам в этом поможет. Спасибо за внимание!
img
Семантическое управление версиями (или семвер) – это формальное соглашение для определения номера версии новых выпусков программного обеспечения. Стандарт помогает пользователям программного обеспечения понять серьезность изменений в каждом новом дистрибутиве. Проект, использующий семантическое управление версиями, объявляет основной номер версии (major), дополнительный номер версии (minor) и номер исправления (patch) для каждого выпуска. Строка версии 1.2.3 указывает на основную версию под номером 1, дополнительную версию под номером 2 и исправление под номером 3. Номера версий такого формата широко используются как программными пакетами, так и исполняемыми файлами конечных пользователей, такими как приложения и игры. Однако не каждый проект точно следует стандарту, установленному semver.org. Спецификация была создана для решения проблем, вызванных несовместимостью методов управления версиями между программными пакетами, используемыми в качестве зависимостей. Под «пакетом» и «зависимостью» мы подразумеваем библиотеку кода, предназначенную для использования в другом программном проекте и распространяемую диспетчером пакетов, таким как npm, composer или nuget. Это именно то применение семантического управления версиями, которое мы рассматриваем в этой статье. Major, Minor и Patch Важно понимать значение трех задействованных компонентов. Вместе они намечают путь разработки проекта и соотносят влияние каждого нового выпуска на конечных пользователей. Major number (основной номер версии) – основной номер указывает на текущую версию общедоступного интерфейса пакета. Он увеличивается каждый раз, когда вы вносите изменения, которые требуют от существующих пользователей вашего пакета обновления их собственной работы. Minor number (дополнительный номер версии) – дополнительный номер указывает на текущую функциональную версию вашего программного обеспечения. Он увеличивается всякий раз, когда вы добавляете новую функцию, но не меняете интерфейс вашего пакета. Он сообщает пользователям о том, что были внесены значительные изменения, но пакет полностью совместимым с предыдущими версиями с предыдущим дополнительным номером. Patch number (номер исправления) – номер исправления увеличивается каждый раз, когда вы вносите какое-то незначительное изменение, которое не влияет на общедоступный интерфейс или общую функциональность вашего пакета. Его чаще всего используют для исправления ошибок. Потребители всегда должны иметь возможность не задумываясь установить последнюю версию исправлений. Семантическая структура версии выпуска лучше всего моделируется в виде дерева. Наверху у вас изменения общедоступного интерфейса, каждое из которых отображается на основном номере. Каждая основная версия имеет свой собственный набор дополнительных версий, в которые добавляются новые функции без нарушения совместимости с предыдущими версиями. И наконец, дополнительные версии могут время от времени отлаживаться путем исправления некоторых ошибок. Откуда начинать? Большинство проектов должны начинаться с версии 1.0.0. Вы публикуете свой первый общедоступный интерфейс и первоначальный неизмененный набор функций. И поскольку вам еще не приходилось вносить никаких исправления, то и версия исправления – 0. Теперь давайте посмотрим, что же происходит, когда вы вносите изменения в свой пакет. После вашего первоначального выпуска вы получаете отчет об ошибке от пользователя. Когда вы выпустите исправление, то правильный номер версии уже будет 1.0.1. Если бы вы затем выпустили еще одну версию с исправлением ошибок, то вы бы увеличили номер исправления до 2, т.е. номер версии уже был бы 1.0.2. Тем временем вы также работали над новой интересной функцией. Это совершенно необязательно, поэтому пользователям не нужно ничего делать для обновления. Вы выпускаете эту версию как 1.1.0. – создана новая функциональная среда, но ее еще ни разу не исправляли. К сожалению, скоро приходят отчеты об ошибках, и среди ваших пользователей начинает распространяться версия 1.1.1. Несколько месяцев спустя вы решили провести реорганизацию кода всего проекта. Некоторые функции были удалены или теперь доступны через объединенный интерфейс. Если вы выпустите эту работу, то люди, использующие текущую версию вашего пакета, должны будут внести серьезные изменения в свой проект. Пришло время опубликовать 2.0.0. в вашем репозитории пакетов. Поддержание старых веток Увеличение какого-либо номера в вашей строке версий не создает точку невозврата. После публикации 1.1.1 вы могли обнаружить ошибку, присутствующую в 1.0.2. Используя ветки в вашей системе контроля версий, вы можете произвести исправления в обеих версиях. В итоге вы получите 1.1.2 и 1.0.3. Точно также вы можете поддерживать ветку 1.х вашего проекта, несмотря на выпуск 2.0.0. Может показаться странным публиковать 1.1.2 после 2.0.1, но это вполне нормальная практика. Семантическое управление версиями не создает линейный постоянно увеличивающийся номер версии; наоборот, оно предназначено для использования в качестве части модели разработки ветвления, которое использует простоту установки исправлений, предлагаемую системами управления исходным кодом, такими как Git. Опубликованные версии должны быть неизменяемыми. После того, как вы создали версию 2.4.3, вы не можете «обновить» его, просто добавив дополнительный код в ту же строку версии. Вы должны присваивать новый номер версии каждому выпуску, чтобы пользователи всегда могли получить доступ к каждой конкретной версии вашего пакета. Обработка пакетов, находящихся в стадии разработки Как правило, вы всегда обновляете основную версию своего пакета всякий раз, когда вносятся изменения, несовместимые с предыдущими версиями. Когда вы находитесь в стадии разработки, то ваша кодовая база может дорабатываться очень быстро, что приводит к публикации множества основных версий. Вы можете этого избежать, рекламируя свой проект как 0.y.z. Значение 0 в качестве основной версии означает, что ваш пакет неустойчив. Обычные правила в отношении совместимости с предыдущими версиями тут не применяются, поэтому вы можете выпускать новые версии, увеличивая только дополнительный номер и номер исправления. Это значит, что вы можете использовать 1.0.0 для обозначения первой «завершенной» версии вашего программного обеспечения. Вы также можете добавить дополнительные «идентификаторы» в конец строки версии, используя дефис в качестве разделителя: 1.0.0-alpha.1. Вы можете использовать такой вариант для того, чтобы четко обозначить альфа- и бета-версии. Точно также вы можете включить метаданные сборки, добавив символ +: 1.1.0-alpha.1+linux_x86. Заключение Согласованное использование семантического управления версиями помогает пользователям быть уверенными в вашем проекте. Они могут четко видеть, как развивается ваша кодовая база и нужно ли им самим провести какую-то работу, чтобы идти в ногу со временем. Объявление строки семантической версии необходимо при публикации в диспетчере наиболее популярных пакетов. Тем не менее, в конечном счете, вам решать, какие номера вы устанавливаете для каждого нового выпуска. Соблюдение стандарта четко сообщает о ваших намерениях пользователям и сводит к минимуму риск непреднамеренного нарушения чужой работы.
ВЕСЕННИЕ СКИДКИ
40%
50%
60%
До конца акции: 30 дней 24 : 59 : 59