public function actionInfo()
    {
        $items = [
            'framework',
            'app-basic',
            'app-advanced',
        ];
        $extensionPath = "{$this->basePath}/extensions";
        foreach (scandir($extensionPath) as $extension) {
            if (ctype_alpha($extension) && is_dir($extensionPath . '/' . $extension)) {
                $items[] = $extension;
            }
        }

        if ($this->update) {
            foreach ($items as $item) {
                $this->stdout("fetching tags for $item...");
                if ($item === 'framework') {
                    $this->gitFetchTags((string)$this->basePath);
                } elseif (strncmp('app-', $item, 4) === 0) {
                    $this->gitFetchTags("{$this->basePath}/apps/" . substr($item, 4));
                } else {
                    $this->gitFetchTags("{$this->basePath}/extensions/$item");
                }
                $this->stdout("done.\n", Console::FG_GREEN, Console::BOLD);
            }
        } else {
            $this->stdout("\nInformation may be outdated, re-run with `--update` to fetch latest tags.\n\n");
        }

        $versions = $this->getCurrentVersions($items);
        $nextVersions = $this->getNextVersions($versions, self::PATCH);

        // print version table
        $w = $this->minWidth(array_keys($versions));
        $this->stdout(str_repeat(' ', $w + 2) . "Current Version  Next Version\n", Console::BOLD);
        foreach ($versions as $ext => $version) {
            $this->stdout($ext . str_repeat(' ', $w + 3 - mb_strlen($ext)) . $version . '');
            $this->stdout(str_repeat(' ', 17 - mb_strlen($version)) . $nextVersions[$ext] . "\n");
        }
    }