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