xref: /dokuwiki/.github/release.php (revision 017f2aa27bddfec183008cd45bcabe32599bc2c3)
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