// Most of this logic is from // https://github.com/MSP-Greg/actions-ruby/blob/master/lib/main.js const fs = require('fs') const path = require('path') const cp = require('child_process') const core = require('@actions/core') const exec = require('@actions/exec') const tc = require('@actions/tool-cache') const common = require('./common') const rubyInstallerVersions = require('./windows-versions').versions // Extract to SSD, see https://github.com/ruby/setup-ruby/pull/14 const drive = (process.env['GITHUB_WORKSPACE'] || 'C')[0] // needed for 2.1, 2.2, 2.3, and mswin, cert file used by Git for Windows const certFile = 'C:\\Program Files\\Git\\mingw64\\ssl\\cert.pem' // standard MSYS2 location, found by 'devkit.rb' const msys2 = 'C:\\msys64' const msys2PathEntries = [`${msys2}\\mingw64\\bin`, `${msys2}\\usr\\bin`] // location & path for old RubyInstaller DevKit (MSYS), Ruby 2.1, 2.2 and 2.3 const msys = `${drive}:\\DevKit64` const msysPathEntries = [`${msys}\\mingw\\x86_64-w64-mingw32\\bin`, `${msys}\\mingw\\bin`, `${msys}\\bin`] export function getAvailableVersions(platform, engine) { if (engine === 'ruby') { return Object.keys(rubyInstallerVersions) } else { return undefined } } export async function install(platform, engine, version) { const url = rubyInstallerVersions[version] if (!url.endsWith('.7z')) { throw new Error(`URL should end in .7z: ${url}`) } const base = url.slice(url.lastIndexOf('/') + 1, url.length - '.7z'.length) const downloadPath = await common.measure('Downloading Ruby', async () => { console.log(url) return await tc.downloadTool(url) }) await common.measure('Extracting Ruby', async () => exec.exec('7z', ['x', downloadPath, `-xr!${base}\\share\\doc`, `-o${drive}:\\`], { silent: true })) const rubyPrefix = `${drive}:\\${base}` let toolchainPaths = (version === 'mswin') ? await setupMSWin() : await setupMingw(version) const newPathEntries = [`${rubyPrefix}\\bin`, ...toolchainPaths] return [rubyPrefix, newPathEntries] } // Remove when Actions Windows image contains MSYS2 install async function symLinkToEmbeddedMSYS2() { const toolCacheVersions = tc.findAllVersions('Ruby') toolCacheVersions.sort() if (toolCacheVersions.length === 0) { throw new Error('Could not find MSYS2 in the toolcache') } const latestVersion = toolCacheVersions.slice(-1)[0] const hostedRuby = tc.find('Ruby', latestVersion) await common.measure('Linking MSYS2', async () => exec.exec(`cmd /c mklink /D ${msys2} ${hostedRuby}\\msys64`)) } async function setupMingw(version) { core.exportVariable('MAKE', 'make.exe') if (version.match(/^2\.[123]/)) { core.exportVariable('SSL_CERT_FILE', certFile) await common.measure('Installing MSYS1', async () => installMSYS(version)) return msysPathEntries } else { // Remove when Actions Windows image contains MSYS2 install if (!fs.existsSync(msys2)) { await symLinkToEmbeddedMSYS2() } return msys2PathEntries } } // Ruby 2.1, 2.2 and 2.3 async function installMSYS(version) { const url = 'https://dl.bintray.com/oneclick/rubyinstaller/DevKit-mingw64-64-4.7.2-20130224-1432-sfx.exe' const downloadPath = await tc.downloadTool(url) await exec.exec('7z', ['x', downloadPath, `-o${msys}`], { silent: true }) // below are set in the old devkit.rb file ? core.exportVariable('RI_DEVKIT', msys) core.exportVariable('CC' , 'gcc') core.exportVariable('CXX', 'g++') core.exportVariable('CPP', 'cpp') core.info(`Installed RubyInstaller DevKit for Ruby ${version}`) } async function setupMSWin() { core.exportVariable('MAKE', 'nmake.exe') // All standard MSVC OpenSSL builds use C:\Program Files\Common Files\SSL const certsDir = 'C:\\Program Files\\Common Files\\SSL\\certs' if (!fs.existsSync(certsDir)) { fs.mkdirSync(certsDir) } // cert.pem location is hard-coded by OpenSSL msvc builds const cert = 'C:\\Program Files\\Common Files\\SSL\\cert.pem' if (!fs.existsSync(cert)) { fs.copyFileSync(certFile, cert) } // Remove when Actions Windows image contains MSYS2 install if (!fs.existsSync(msys2)) { await symLinkToEmbeddedMSYS2() } const VCPathEntries = await common.measure('Setting up MSVC environment', async () => addVCVARSEnv()) return [...VCPathEntries, ...msys2PathEntries] } /* Sets MSVC environment for use in Actions * allows steps to run without running vcvars*.bat, also for PowerShell * adds a convenience VCVARS environment variable * this assumes a single Visual Studio version being available in the windows-latest image */ export function addVCVARSEnv() { const vcVars = '"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Enterprise\\VC\\Auxiliary\\Build\\vcvars64.bat"' core.exportVariable('VCVARS', vcVars) let newEnv = new Map() let cmd = `cmd.exe /c "${vcVars} && set"` let newSet = cp.execSync(cmd).toString().trim().split(/\r?\n/) newSet = newSet.filter(line => line.match(/\S=\S/)) newSet.forEach(s => { let [k,v] = s.split('=', 2) newEnv.set(k,v) }) let newPathEntries = undefined for (let [k, v] of newEnv) { if (process.env[k] !== v) { if (k === 'Path') { newPathEntries = v.replace(process.env['Path'], '').split(path.delimiter) } else { core.exportVariable(k, v) } } } return newPathEntries }