()
| 149 | } |
| 150 | |
| 151 | function installDocker() { |
| 152 | const os = getPlatform() |
| 153 | const instructions = docker[os] |
| 154 | const displayName = docker.name |
| 155 | |
| 156 | if (!instructions) { |
| 157 | console.error(`\n⚠️ Cannot install ${displayName} on ${os}`) |
| 158 | console.error( |
| 159 | `Please install ${displayName} manually: ${instructions?.manual || 'https://docs.docker.com/get-docker/'}`, |
| 160 | ) |
| 161 | return false |
| 162 | } |
| 163 | |
| 164 | // macOS: Install Docker Desktop via Homebrew |
| 165 | if (os === 'macos' && instructions.brew && checkBrewAvailable()) { |
| 166 | try { |
| 167 | console.log(`\n📦 Installing ${displayName} Desktop via Homebrew...`) |
| 168 | execSync(instructions.brew, { stdio: 'inherit' }) |
| 169 | console.log(`\n✅ ${displayName} Desktop installed successfully`) |
| 170 | console.log( |
| 171 | `\n⚠️ Please start Docker Desktop from Applications and ensure it's running before continuing.`, |
| 172 | ) |
| 173 | return true |
| 174 | } catch (error) { |
| 175 | console.error(`\n⚠️ Homebrew installation failed: ${error.message}`) |
| 176 | console.error(`Please install manually: ${instructions.manual}`) |
| 177 | return false |
| 178 | } |
| 179 | } |
| 180 | |
| 181 | // Linux: Install Docker Engine via official repository |
| 182 | if (os === 'linux') { |
| 183 | try { |
| 184 | console.log(`\n📦 Installing ${displayName} Engine...`) |
| 185 | console.log(` Setting up Docker's official APT repository...`) |
| 186 | |
| 187 | // Detect distribution |
| 188 | let distro = 'debian' |
| 189 | let codename = 'bookworm' |
| 190 | try { |
| 191 | const osRelease = execSync('cat /etc/os-release', { encoding: 'utf-8' }) |
| 192 | if (osRelease.includes('Ubuntu')) { |
| 193 | distro = 'ubuntu' |
| 194 | const match = osRelease.match(/UBUNTU_CODENAME=(\w+)/) |
| 195 | if (match) codename = match[1] |
| 196 | else { |
| 197 | const versionMatch = osRelease.match(/VERSION_ID="?(\d+\.\d+)/) |
| 198 | if (versionMatch) { |
| 199 | const version = parseFloat(versionMatch[1]) |
| 200 | if (version >= 24.04) codename = 'noble' |
| 201 | else if (version >= 22.04) codename = 'jammy' |
| 202 | else if (version >= 20.04) codename = 'focal' |
| 203 | } |
| 204 | } |
| 205 | } else { |
| 206 | const match = osRelease.match(/VERSION_CODENAME=(\w+)/) |
| 207 | if (match) codename = match[1] |
| 208 | } |
no test coverage detected