1 | "use strict";
|
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
4 | };
|
5 | Object.defineProperty(exports, "__esModule", { value: true });
|
6 | const fs_1 = __importDefault(require("fs"));
|
7 | const path_1 = require("path");
|
8 | const util_1 = require("util");
|
9 | const execa_1 = __importDefault(require("execa"));
|
10 | const fs_extra_1 = require("fs-extra");
|
11 | const micromatch_1 = __importDefault(require("micromatch"));
|
12 | const readFile = util_1.promisify(fs_1.default.readFile);
|
13 | const writeFile = util_1.promisify(fs_1.default.writeFile);
|
14 | const stat = util_1.promisify(fs_1.default.stat);
|
15 | const build_utils_1 = require("@now/build-utils");
|
16 | const gem_install_1 = require("./gem-install");
|
17 | const REQUIRED_VENDOR_DIR = 'vendor/bundle/ruby/2.5.0';
|
18 | async function dirExists(directory) {
|
19 | let dirStat;
|
20 | try {
|
21 | dirStat = await stat(directory);
|
22 | }
|
23 | catch (e) {
|
24 | return false;
|
25 | }
|
26 | return dirStat.isDirectory();
|
27 | }
|
28 | async function gemInstall(gemPath, vendorDir, gems) {
|
29 | console.log(`running "gem install ${gems.join(' ')}"...`);
|
30 | try {
|
31 | await execa_1.default(gemPath, ['install', '--install-dir', vendorDir, '--no-document', ...gems], {
|
32 | stdio: 'inherit',
|
33 | });
|
34 | }
|
35 | catch (err) {
|
36 | console.log(`failed to run "gem install ${gems.join(' ')}"...`);
|
37 | throw err;
|
38 | }
|
39 | }
|
40 | async function bundleInstall(bundlePath, bundleDir, gemfilePath) {
|
41 | console.log(`running "bundle install --deployment"...`);
|
42 | try {
|
43 | await execa_1.default(bundlePath, [
|
44 | 'install',
|
45 | '--deployment',
|
46 | '--gemfile',
|
47 | gemfilePath,
|
48 | '--path',
|
49 | bundleDir,
|
50 | ], {
|
51 | stdio: 'inherit',
|
52 | env: {
|
53 | BUNDLE_SILENCE_ROOT_WARNING: '1',
|
54 | },
|
55 | });
|
56 | }
|
57 | catch (err) {
|
58 | console.log(`failed to run "bundle install --deployment"...`);
|
59 | throw err;
|
60 | }
|
61 | }
|
62 | exports.config = {
|
63 | maxLambdaSize: '5mb',
|
64 | };
|
65 | exports.build = async ({ workPath, files, entrypoint, config, }) => {
|
66 | console.log('downloading files...');
|
67 |
|
68 | files = await build_utils_1.download(files, workPath);
|
69 |
|
70 |
|
71 | const gemHome = await build_utils_1.getWriteableDirectory();
|
72 | process.env.GEM_HOME = gemHome;
|
73 | const { gemPath, bundlerPath } = await gem_install_1.downloadAndInstallBundler();
|
74 | const fsFiles = await build_utils_1.glob('**', workPath);
|
75 | const entryDirectory = path_1.dirname(entrypoint);
|
76 | const fsEntryDirectory = path_1.dirname(fsFiles[entrypoint].fsPath);
|
77 |
|
78 | console.log('checking for existing vendor directory at', '"' + REQUIRED_VENDOR_DIR + '"');
|
79 | const vendorDir = path_1.join(workPath, REQUIRED_VENDOR_DIR);
|
80 | const bundleDir = path_1.join(workPath, 'vendor/bundle');
|
81 | const relativeVendorDir = path_1.join(fsEntryDirectory, REQUIRED_VENDOR_DIR);
|
82 | let hasRootVendorDir = await dirExists(vendorDir);
|
83 | let hasRelativeVendorDir = await dirExists(relativeVendorDir);
|
84 | let hasVendorDir = hasRootVendorDir || hasRelativeVendorDir;
|
85 | if (hasRelativeVendorDir) {
|
86 | if (hasRootVendorDir) {
|
87 | console.log('found two vendor directories, choosing the vendor directory relative to entrypoint');
|
88 | }
|
89 | else {
|
90 | console.log('found vendor directory relative to entrypoint');
|
91 | }
|
92 |
|
93 | await fs_extra_1.move(relativeVendorDir, vendorDir);
|
94 | }
|
95 | else if (hasRootVendorDir) {
|
96 | console.log('found vendor directory in project root');
|
97 | }
|
98 | await fs_extra_1.ensureDir(vendorDir);
|
99 |
|
100 | await gemInstall(gemPath, vendorDir, ['httparty']);
|
101 |
|
102 | if (!hasVendorDir) {
|
103 | const gemFile = path_1.join(entryDirectory, 'Gemfile');
|
104 | if (fsFiles[gemFile]) {
|
105 | console.log('did not find a vendor directory but found a Gemfile, bundling gems...');
|
106 | const gemfilePath = fsFiles[gemFile].fsPath;
|
107 |
|
108 |
|
109 | try {
|
110 | await bundleInstall(bundlerPath, bundleDir, gemfilePath);
|
111 | }
|
112 | catch (err) {
|
113 | console.log('unable to build gems from Gemfile. vendor the gems locally with "bundle install --deployment" and retry.');
|
114 | throw err;
|
115 | }
|
116 | }
|
117 | }
|
118 | else {
|
119 | console.log('found vendor directory, skipping "bundle install"...');
|
120 | }
|
121 |
|
122 | try {
|
123 | await fs_extra_1.remove(path_1.join(vendorDir, 'cache'));
|
124 | }
|
125 | catch (e) { }
|
126 | console.log('calculating size of vendor directory...');
|
127 | await execa_1.default('du', ['-hs', vendorDir], { stdio: 'inherit' });
|
128 | const originalRbPath = path_1.join(__dirname, 'now_init.rb');
|
129 | const originalNowHandlerRbContents = await readFile(originalRbPath, 'utf8');
|
130 |
|
131 |
|
132 | console.log('entrypoint is', entrypoint);
|
133 | const userHandlerFilePath = entrypoint.replace(/\.rb$/, '');
|
134 | const nowHandlerRbContents = originalNowHandlerRbContents.replace(/__NOW_HANDLER_FILENAME/g, userHandlerFilePath);
|
135 |
|
136 |
|
137 | const nowHandlerRbFilename = 'now__handler__ruby';
|
138 | await writeFile(path_1.join(workPath, `${nowHandlerRbFilename}.rb`), nowHandlerRbContents);
|
139 | let outputFiles = await build_utils_1.glob('**', workPath);
|
140 |
|
141 |
|
142 | if (config && (config.include || config.exclude)) {
|
143 | let outputPaths = Object.keys(outputFiles);
|
144 | let notIncluded = config.include
|
145 | ? micromatch_1.default.not(outputPaths, config.include)
|
146 | : outputPaths;
|
147 | let excluded = config.exclude ? micromatch_1.default(notIncluded, config.exclude) : [];
|
148 | for (let i = 0; i < excluded.length; i++) {
|
149 |
|
150 | if (excluded[i] === `${nowHandlerRbFilename}.rb`) {
|
151 | continue;
|
152 | }
|
153 |
|
154 | if (excluded[i].startsWith(REQUIRED_VENDOR_DIR)) {
|
155 | continue;
|
156 | }
|
157 | delete outputFiles[excluded[i]];
|
158 | }
|
159 | }
|
160 | const lambda = await build_utils_1.createLambda({
|
161 | files: outputFiles,
|
162 | handler: `${nowHandlerRbFilename}.now__handler`,
|
163 | runtime: 'ruby2.5',
|
164 | environment: {},
|
165 | });
|
166 | return {
|
167 | [entrypoint]: lambda,
|
168 | };
|
169 | };
|