private function generateNextVersion($currentVersion) {
      $type = $this->releaseType;

      $label = isset($this->options['label']) ? $this->options['label'] : 'none';

      // Type validation
      $validTypes = ['patch', 'minor', 'major'];
      if (!in_array($type, $validTypes)) {
         throw new \InvalidArgumentException(
            'The option [type] must be one of: {' . implode($validTypes,
               ', ') . "}, \"$type\" given"
         );
      }

      $versionRegex = '(?:(\d+\.\d+\.\d+)(?:(-)([a-zA-Z]+)(\d+)?)?)';
      if (!preg_match('#^' . $versionRegex . '$#', $currentVersion)) {
         throw new \Exception('Current version format is invalid (' . $currentVersion . '). It should be major.minor.patch');
      }

      $matches = null;
      preg_match('$' . $versionRegex . '$', $currentVersion, $matches);
      // if last version is with label
      if (count($matches) > 3) {
         list($major, $minor, $patch) = explode('.', $currentVersion);
         $patch = substr($patch, 0, strpos($patch, '-'));

         if ($label != 'none') {
            // increment label
            $labelVersion = '';
            if (array_key_exists(3, $matches)) {
               $oldLabel = $matches[3];
               $labelVersion = 2;

               // if label is new clear version
               if ($label !== $oldLabel) {
                  $labelVersion = false;
               } else if (array_key_exists(4, $matches)) {
                  // if version exists increment it
                  $labelVersion = intval($matches[4]) + 1;
               }
            }

            return implode([$major, $minor, $patch], '.') . '-' . $label . $labelVersion;
         }

         return implode([$major, $minor, $patch], '.');
      }

      list($major, $minor, $patch) = explode('.', $currentVersion);
      // Increment
      switch ($type) {
         case 'major':
            $major += 1;
            $patch = $minor = 0;
            break;
         case 'minor':
            $minor += 1;
            $patch = 0;
            break;
         default:
            $patch += 1;
            break;
      }

      // new label
      if ($label != 'none') {
         return implode([$major, $minor, $patch], '.') . '-' . $label;
      }

      return implode([$major, $minor, $patch], '.');
   }