aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/.github/release.php
blob: 7a9a9462fb1d3f27f4e7e56f2e604e6044718d19 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
<?php

if (!defined('DOKU_INC')) define('DOKU_INC', __DIR__ . '/../');
require_once(DOKU_INC . 'vendor/autoload.php');
require_once DOKU_INC . 'inc/load.php';

/**
 * Command Line utility to gather and check data for building a release
 */
class Release extends splitbrain\phpcli\CLI
{
    const TYPES = ['stable', 'hotfix', 'rc'];

    // base URL to fetch raw files from the stable branch
    protected $BASERAW = 'https://raw.githubusercontent.com/dokuwiki/dokuwiki/stable/';

    /** @inheritdoc */
    public function __construct($autocatch = true)
    {
        parent::__construct($autocatch);

        // when running on a clone, use the correct base URL
        $repo = getenv('GITHUB_REPOSITORY');
        if ($repo) {
            $this->BASERAW = 'https://raw.githubusercontent.com/' . $repo . '/stable/';
        }
    }


    protected function setup(\splitbrain\phpcli\Options $options)
    {
        $options->setHelp('This tool is used to gather and check data for building a release');

        $options->registerCommand('new', 'Get environment for creating a new release');
        $options->registerOption('type', 'The type of release to build', null, join('|', self::TYPES), 'new');
        $options->registerOption('date', 'The date to use for the version. Defaults to today', null, 'YYYY-MM-DD', 'new');
        $options->registerOption('name', 'The codename to use for the version. Defaults to the last used one', null, 'codename', 'new');

        $options->registerCommand('current', 'Get environment of the current release');
    }

    protected function main(\splitbrain\phpcli\Options $options)
    {
        switch ($options->getCmd()) {
            case 'new':
                $this->prepareNewEnvironment($options);
                break;
            case 'current':
                $this->prepareCurrentEnvironment($options);
                break;
            default:
                echo $options->help();
        }
    }

    /**
     * Prepare environment for the current branch
     */
    protected function prepareCurrentEnvironment(\splitbrain\phpcli\Options $options)
    {
        $current = $this->getLocalVersion();
        // we name files like the string in the VERSION file, with rc at the front
        $current['file'] = ($current['type'] === 'rc' ? 'rc' : '') . $current['date'] . $current['hotfix'];

        // output to be piped into GITHUB_ENV
        foreach ($current as $k => $v) {
            echo "current_$k=$v\n";
        }
    }

    /**
     * Prepare environment for creating a new release
     */
    protected function prepareNewEnvironment(\splitbrain\phpcli\Options $options)
    {
        $current = $this->getUpstreamVersion();

        // continue if we want to create a new release
        $next = [
            'type' => $options->getOpt('type'),
            'date' => $options->getOpt('date'),
            'codename' => $options->getOpt('name'),
            'hotfix' => '',
        ];
        if (!$next['type']) $next['type'] = 'stable';
        if (!$next['date']) $next['date'] = date('Y-m-d');
        if (!$next['codename']) $next['codename'] = $current['codename'];
        $next['codename'] = ucwords(strtolower($next['codename']));

        if (!in_array($next['type'], self::TYPES)) {
            throw new \splitbrain\phpcli\Exception('Invalid release type. Use one of ' . join(', ', self::TYPES));
        }

        if ($next['type'] === 'hotfix') {
            $next['update'] = floatval($current['update']) + 0.1;
            $next['codename'] = $current['codename'];
            $next['date'] = $current['date'];
            $next['hotfix'] = $this->increaseHotfix($current['hotfix']);
        } else {
            $next['update'] = intval($current['update']) + 1;
        }

        if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $next['date'])) {
            throw new \splitbrain\phpcli\Exception('Invalid date format, use YYYY-MM-DD');
        }

        if ($current['date'] > $next['date']) {
            throw new \splitbrain\phpcli\Exception('Date must be equal or later than the last release');
        }

        if ($current['type'] === 'rc' && $next['type'] === 'hotfix') {
            throw new \splitbrain\phpcli\Exception(
                'Cannot create hotfixes for release candidates, create a new RC instead'
            );
        }

        if ($current['type'] === 'stable' && $next['type'] !== 'hotfix' && $current['codename'] === $next['codename']) {
            throw new \splitbrain\phpcli\Exception('Codename must be different from the last release');
        }

        $next['version'] = $next['date'] . ($next['type'] === 'rc' ? 'rc' : $next['hotfix']);
        $next['raw'] = ($next['type'] === 'rc' ? 'rc' : '') .
            $next['date'] .
            $next['hotfix'] .
            ' "' . $next['codename'] . '"';

        // output to be piped into GITHUB_ENV
        foreach ($current as $k => $v) {
            echo "current_$k=$v\n";
        }
        foreach ($next as $k => $v) {
            echo "next_$k=$v\n";
        }
    }

    /**
     * Get current version info from local VERSION file
     *
     * @return string[]
     */
    protected function getLocalVersion()
    {
        $versioninfo = \dokuwiki\Info::parseVersionString(trim(file_get_contents('VERSION')));
        $doku = file_get_contents('doku.php');
        if (!preg_match('/\$updateVersion = "(\d+(\.\d+)?)";/', $doku, $m)) {
            throw new \Exception('Could not find $updateVersion in doku.php');
        }
        $versioninfo['update'] = floatval($m[1]);
        return $versioninfo;
    }

    /**
     * Get current version info from stable branch
     *
     * @return string[]
     * @throws Exception
     */
    protected function getUpstreamVersion()
    {
        // basic version info
        $versioninfo = \dokuwiki\Info::parseVersionString(trim(file_get_contents($this->BASERAW . 'VERSION')));

        // update version grepped from the doku.php file
        $doku = file_get_contents($this->BASERAW . 'doku.php');
        if (!preg_match('/\$updateVersion = "(\d+(\.\d+)?)";/', $doku, $m)) {
            throw new \Exception('Could not find $updateVersion in doku.php');
        }
        $versioninfo['update'] = floatval($m[1]);

        return $versioninfo;
    }

    /**
     * Increase the hotfix letter
     *
     * (max 26 hotfixes)
     *
     * @param string $hotfix
     * @return string
     */
    protected function increaseHotfix($hotfix)
    {
        if (empty($hotfix)) return 'a';
        return substr($hotfix, 0, -1) . chr(ord($hotfix) + 1);
    }
}

(new Release())->run();