import { join } from 'path'; import fetch from 'node-fetch'; import execa from 'execa'; import { createWriteStream } from 'fs'; import { getWriteableDirectory } from '@now/build-utils'; const url = 'https://portableruby.s3.amazonaws.com/ruby-2.5.3.zip'; // downloads `ruby` and `gem` and returns their absolute paths async function downloadPortableRuby(path: string) { console.log('downloading "ruby-2.5.5.zip"...'); const res = await fetch(url); if (!res.ok || res.status !== 200) { throw new Error(`Could not download "ruby-2.5.3.zip" from "${url}"`); } const dir = await getWriteableDirectory(); const filePath = join(dir, 'ruby-2.5.3.zip'); const writeStream = createWriteStream(filePath); await new Promise((resolve, reject) => { res.body .on('error', reject) .pipe(writeStream) .on('finish', resolve); }); try { await execa('unzip', ['-q', '-d', path, filePath], { stdio: 'inherit' }); } catch (err) { console.log('could not unzip ruby-2.5.3.zip'); throw err; } return { rubyPath: join(path, 'bin', 'ruby'), gemPath: join(path, 'bin', 'gem'), } } // downloads and installs `bundler` (respecting // process.env.GEM_HOME), and returns // the absolute path to it export async function downloadAndInstallBundler() { const { GEM_HOME } = process.env; if (!GEM_HOME) { // this is the directory in which `gem` will be // installed to. `--prefix` will assume `~` if this // is not set, and `~` is not writeable on AWS Lambda. // let's refuse to proceed throw new Error( 'Could not install "bundler": "GEM_HOME" env var is not set', ); } console.log('installing ruby...') const { rubyPath, gemPath } = await downloadPortableRuby(GEM_HOME); console.log('installing bundler...') await execa(gemPath, ['install', 'bundler', '--no-document'], { stdio: 'inherit' }) return { rubyPath, gemPath, bundlerPath: join(GEM_HOME, 'bin', 'bundler'), }; }