UNPKG

5.26 kBJavaScriptView Raw
1"use strict";
2var __importDefault = (this && this.__importDefault) || function (mod) {
3 return (mod && mod.__esModule) ? mod : { "default": mod };
4};
5Object.defineProperty(exports, "__esModule", { value: true });
6const PackageGenerator_1 = __importDefault(require("./PackageGenerator"));
7/**
8 * A Dockerfile generator for R packages
9 */
10class RGenerator extends PackageGenerator_1.default {
11 constructor(urlFetcher, pkg, folder) {
12 super(urlFetcher, pkg, folder);
13 // Default to yesterday's date (to ensure MRAN is available for the date)
14 // Set here as it is required in two methods below
15 let date = this.package.datePublished;
16 if (!date)
17 date = (new Date(Date.now() - 24 * 3600 * 1000)).toISOString().substring(0, 10);
18 this.date = date;
19 }
20 // Methods that override those in `Generator`.
21 // See that class for documentation on what each function does
22 applies() {
23 return this.package.runtimePlatform === 'R';
24 }
25 envVars(sysVersion) {
26 return [
27 // Set the timezone to avoid warning from Sys.timezone()
28 // See https://github.com/rocker-org/rocker-versioned/issues/89
29 ['TZ', 'Etc/UTC']
30 ];
31 }
32 aptKeysCommand(sysVersion) {
33 return 'apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 51716619E084DAB9';
34 }
35 aptRepos(base) {
36 let version = this.baseVersionName(base);
37 // At time of writing, MRAN did not have an ubuntu:18.04(bionic) repo which supported R 3.4 (only bionic_3.5)
38 // See https://cran.microsoft.com/snapshot/2018-11-05/bin/linux/ubuntu/
39 // So append that to the deb line
40 if (version === 'bionic')
41 version += '-cran35';
42 return [
43 `deb https://mran.microsoft.com/snapshot/${this.date}/bin/linux/ubuntu ${version}/`
44 ];
45 }
46 aptPackages(sysVersion) {
47 let pkgs = [
48 'r-base'
49 ];
50 /**
51 * Recurse through `softwareRequirements` and find any deb packages
52 */
53 function find(pkg) {
54 if (pkg.runtimePlatform !== 'R' || !pkg.softwareRequirements)
55 return;
56 for (let subpkg of pkg.softwareRequirements) {
57 if (subpkg.runtimePlatform === 'deb')
58 pkgs.push(subpkg.name || '');
59 else
60 find(subpkg);
61 }
62 }
63 find(this.package);
64 return pkgs;
65 }
66 stencilaInstall(sysVersion) {
67 return `apt-get update \\
68 && apt-get install -y zlib1g-dev libxml2-dev pkg-config \\
69 && apt-get autoremove -y \\
70 && apt-get clean \\
71 && rm -rf /var/lib/apt/lists/* \\
72 && Rscript -e 'install.packages("devtools")' \\
73 && Rscript -e 'source("https://bioconductor.org/biocLite.R"); biocLite("graph")' \\
74 && Rscript -e 'devtools::install_github("r-lib/pkgbuild")' \\
75 && Rscript -e 'devtools::install_github("stencila/r")'`;
76 }
77 installFiles(sysVersion) {
78 // Copy user defined files if they exist
79 if (this.exists('install.R'))
80 return [['install.R', 'install.R']];
81 if (this.exists('DESCRIPTION'))
82 return [['DESCRIPTION', 'DESCRIPTION']];
83 // Generate a .DESCRIPTION with valid name to copy into image
84 const name = (this.package.name || 'unnamed').replace(/[^a-zA-Z0-9]/, '');
85 const pkgs = this.filterPackages('R').map(pkg => pkg.name);
86 let desc = `Package: ${name}
87Version: 1.0.0
88Date: ${this.date}
89Description: Generated by Dockter ${new Date().toISOString()}.
90 To stop Dockter generating this file and start editing it yourself, rename it to "DESCRIPTION".
91`;
92 if (pkgs.length)
93 desc += `Imports:\n ${pkgs.join(',\n ')}\n`;
94 this.write('.DESCRIPTION', desc);
95 return [['.DESCRIPTION', 'DESCRIPTION']];
96 }
97 installCommand(sysVersion) {
98 if (this.exists('install.R')) {
99 // Run the user supplied installation script
100 return `Rscript install.R`;
101 }
102 else if (this.exists('DESCRIPTION') || this.exists('.DESCRIPTION')) {
103 // To keep the Dockerfile as simple as possible, download and
104 // execute the installation-from-DESCRIPTION script.
105 return `bash -c "Rscript <(curl -sL https://unpkg.com/@stencila/dockter/src/install.R)"`;
106 }
107 }
108 /**
109 * The files to copy into the Docker image
110 *
111 * Copies all `*.R` files to the container
112 */
113 projectFiles() {
114 const rfiles = this.glob('**/*.R');
115 return rfiles.map(file => [file, file]);
116 }
117 /**
118 * The command to execute in a container created from the Docker image
119 *
120 * If there is a top-level `main.R` or `cmd.R` then that will be used,
121 * otherwise, the first `*.R` files by alphabetical order will be used.
122 */
123 runCommand() {
124 const rfiles = this.glob('**/*.R');
125 if (rfiles.length === 0)
126 return;
127 let script;
128 if (rfiles.includes('main.R'))
129 script = 'main.R';
130 else if (rfiles.includes('cmd.R'))
131 script = 'cmd.R';
132 else
133 script = rfiles[0];
134 return `Rscript ${script}`;
135 }
136}
137exports.default = RGenerator;