1<?php 2 3if (!defined('DOKU_INC')) define('DOKU_INC', __DIR__ . '/../'); 4require_once(DOKU_INC . 'vendor/autoload.php'); 5require_once DOKU_INC . 'inc/load.php'; 6 7/** 8 * Command Line utility to gather and check data for building a release 9 */ 10class Release extends splitbrain\phpcli\CLI 11{ 12 const TYPES = ['stable', 'hotfix', 'rc']; 13 14 // base URL to fetch raw files from the stable branch 15 protected $BASERAW = 'https://raw.githubusercontent.com/splitbrain/dokuwiki/stable/'; 16 17 /** @inheritdoc */ 18 public function __construct($autocatch = true) 19 { 20 parent::__construct($autocatch); 21 22 $this->error(print_r($_ENV, true)); 23 24 // when running on a clone, use the correct base URL 25 $repo = getenv('GITHUB_REPOSITORY'); 26 if ($repo) { 27 $this->BASERAW = 'https://raw.githubusercontent.com/' . $repo . '/stable/'; 28 } 29 } 30 31 32 protected function setup(\splitbrain\phpcli\Options $options) 33 { 34 $options->setHelp('This tool is used to gather and check data for building a release'); 35 36 $options->registerCommand('new', 'Get environment for creating a new release'); 37 $options->registerOption('type', 'The type of release to build', null, join('|', self::TYPES), 'new'); 38 $options->registerOption('date', 'The date to use for the version. Defaults to today', null, 'YYYY-MM-DD', 'new'); 39 $options->registerOption('name', 'The codename to use for the version. Defaults to the last used one', null, 'codename', 'new'); 40 41 $options->registerCommand('current', 'Get environment of the current release'); 42 } 43 44 protected function main(\splitbrain\phpcli\Options $options) 45 { 46 switch ($options->getCmd()) { 47 case 'new': 48 $this->prepareNewEnvironment($options); 49 break; 50 case 'current': 51 $this->prepareCurrentEnvironment($options); 52 break; 53 default: 54 echo $options->help(); 55 } 56 } 57 58 /** 59 * Prepare environment for the current branch 60 */ 61 protected function prepareCurrentEnvironment(\splitbrain\phpcli\Options $options) 62 { 63 $current = $this->getLocalVersion(); 64 // we name files like the string in the VERSION file, with rc at the front 65 $current['file'] = ($current['type'] === 'rc' ? 'rc' : '') . $current['date'] . $current['hotfix']; 66 67 // output to be piped into GITHUB_ENV 68 foreach ($current as $k => $v) { 69 echo "current_$k=$v\n"; 70 } 71 } 72 73 /** 74 * Prepare environment for creating a new release 75 */ 76 protected function prepareNewEnvironment(\splitbrain\phpcli\Options $options) 77 { 78 $current = $this->getUpstreamVersion(); 79 80 // continue if we want to create a new release 81 $next = [ 82 'type' => $options->getOpt('type'), 83 'date' => $options->getOpt('date'), 84 'codename' => $options->getOpt('name'), 85 'hotfix' => '', 86 ]; 87 if (!$next['type']) $next['type'] = 'stable'; 88 if (!$next['date']) $next['date'] = date('Y-m-d'); 89 if (!$next['codename']) $next['codename'] = $current['codename']; 90 $next['codename'] = ucwords(strtolower($next['codename'])); 91 92 if (!in_array($next['type'], self::TYPES)) { 93 throw new \splitbrain\phpcli\Exception('Invalid release type. Use one of ' . join(', ', self::TYPES)); 94 } 95 96 if ($next['type'] === 'hotfix') { 97 $next['update'] = floatval($current['update']) + 0.1; 98 $next['codename'] = $current['codename']; 99 $next['date'] = $current['date']; 100 $next['hotfix'] = $this->increaseHotfix($current['hotfix']); 101 } else { 102 $next['update'] = intval($current['update']) + 1; 103 } 104 105 if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $next['date'])) { 106 throw new \splitbrain\phpcli\Exception('Invalid date format, use YYYY-MM-DD'); 107 } 108 109 if ($current['date'] > $next['date']) { 110 throw new \splitbrain\phpcli\Exception('Date must be equal or later than the last release'); 111 } 112 113 if ($current['type'] === 'rc' && $next['type'] === 'hotfix') { 114 throw new \splitbrain\phpcli\Exception( 115 'Cannot create hotfixes for release candidates, create a new RC instead' 116 ); 117 } 118 119 if ($current['type'] === 'stable' && $next['type'] !== 'hotfix' && $current['codename'] === $next['codename']) { 120 throw new \splitbrain\phpcli\Exception('Codename must be different from the last release'); 121 } 122 123 $next['version'] = $next['date'] . ($next['type'] === 'rc' ? 'rc' : $next['hotfix']); 124 $next['raw'] = ($next['type'] === 'rc' ? 'rc' : '') . 125 $next['date'] . 126 $next['hotfix'] . 127 ' "' . $next['codename'] . '"'; 128 129 // output to be piped into GITHUB_ENV 130 foreach ($current as $k => $v) { 131 echo "current_$k=$v\n"; 132 } 133 foreach ($next as $k => $v) { 134 echo "next_$k=$v\n"; 135 } 136 } 137 138 /** 139 * Get current version info from local VERSION file 140 * 141 * @return string[] 142 */ 143 protected function getLocalVersion() 144 { 145 $versioninfo = \dokuwiki\Info::parseVersionString(trim(file_get_contents('VERSION'))); 146 $doku = file_get_contents('doku.php'); 147 if (!preg_match('/\$updateVersion = "(\d+(\.\d+)?)";/', $doku, $m)) { 148 throw new \Exception('Could not find $updateVersion in doku.php'); 149 } 150 $versioninfo['update'] = floatval($m[1]); 151 return $versioninfo; 152 } 153 154 /** 155 * Get current version info from stable branch 156 * 157 * @return string[] 158 * @throws Exception 159 */ 160 protected function getUpstreamVersion() 161 { 162 // basic version info 163 $versioninfo = \dokuwiki\Info::parseVersionString(trim(file_get_contents($this->BASERAW . 'VERSION'))); 164 165 // update version grepped from the doku.php file 166 $doku = file_get_contents($this->BASERAW . 'doku.php'); 167 if (!preg_match('/\$updateVersion = "(\d+(\.\d+)?)";/', $doku, $m)) { 168 throw new \Exception('Could not find $updateVersion in doku.php'); 169 } 170 $versioninfo['update'] = floatval($m[1]); 171 172 return $versioninfo; 173 } 174 175 /** 176 * Increase the hotfix letter 177 * 178 * (max 26 hotfixes) 179 * 180 * @param string $hotfix 181 * @return string 182 */ 183 protected function increaseHotfix($hotfix) 184 { 185 if (empty($hotfix)) return 'a'; 186 return substr($hotfix, 0, -1) . chr(ord($hotfix) + 1); 187 } 188} 189 190(new Release())->run(); 191