1 | import fs from 'fs'
|
2 | import path from 'path'
|
3 | import { spawnSync } from 'child_process'
|
4 | import Docker from 'dockerode'
|
5 | import yaml from 'js-yaml'
|
6 | import NixGenerator from './NixGenerator'
|
7 | import { SoftwareEnvironment } from '@stencila/schema'
|
8 | import CachingUrlFetcher from './CachingUrlFetcher'
|
9 |
|
10 | const generator = new NixGenerator(new CachingUrlFetcher(), undefined)
|
11 | const docker = new Docker()
|
12 |
|
13 |
|
14 |
|
15 |
|
16 | function compile (environ: void | SoftwareEnvironment | null, folder: any) {
|
17 |
|
18 | generator.generate(environ, folder)
|
19 |
|
20 |
|
21 | let defaultNix = path.join(folder, 'default.nix')
|
22 | let dockterNix = path.join(folder, '.default.nix')
|
23 | let nixfile = fs.existsSync(defaultNix) ? defaultNix : dockterNix
|
24 |
|
25 |
|
26 | let dockerfile = path.join(folder, '.nixDockerfile')
|
27 |
|
28 | fs.writeFileSync(dockerfile, `FROM nixos/nix
|
29 |
|
30 | # Copy over the Nix derivation
|
31 | COPY ${path.basename(nixfile)} default.nix
|
32 | # Run nix-shell
|
33 | CMD nix-shell --pure\n`
|
34 | )
|
35 | }
|
36 |
|
37 |
|
38 |
|
39 |
|
40 | async function build (folder: any) {
|
41 | let name = path.basename(folder).toLocaleLowerCase().replace(' ', '-')
|
42 |
|
43 |
|
44 | let defaultNix = path.join(folder, 'default.nix')
|
45 | let dockterNix = path.join(folder, '.default.nix')
|
46 | let nixfile = fs.existsSync(defaultNix) ? defaultNix : dockterNix
|
47 |
|
48 |
|
49 | let build = await docker.buildImage({
|
50 | context: folder,
|
51 | src: ['.nixDockerfile', path.basename(nixfile)]
|
52 | }, { t: name, dockerfile: '.nixDockerfile' })
|
53 |
|
54 |
|
55 | docker.modem.followProgress(build, (err: any, res: any) => {
|
56 | if (err) throw err
|
57 | output(res)
|
58 | })
|
59 | }
|
60 |
|
61 |
|
62 |
|
63 |
|
64 | async function execute (folder: any, command: string = '') {
|
65 |
|
66 | let volumes: any = await docker.listVolumes()
|
67 | let nixStoreVolume = volumes.Volumes.find((vol: any) => (vol.Name === 'nix-store'))
|
68 | if (!nixStoreVolume) { await docker.createVolume({ name: 'nix-store' }) }
|
69 |
|
70 | let name = path.basename(folder).toLocaleLowerCase().replace(' ', '-')
|
71 | let args = `run -it --rm -v /tmp:/tmp -v nix-store:/nix ${name}`
|
72 |
|
73 |
|
74 | if (command) args += ` /root/.nix-profile/bin/nix-shell --pure --run "${command.replace('"', '\\"')}"`
|
75 | spawnSync(
|
76 | 'docker', args.split(' '),
|
77 | {
|
78 | shell: true,
|
79 | cwd: process.cwd(),
|
80 | stdio: 'inherit'
|
81 | }
|
82 | )
|
83 | }
|
84 |
|
85 | export default { compile, build, execute }
|
86 |
|
87 |
|
88 |
|
89 |
|
90 |
|
91 |
|
92 |
|
93 | function output (object: any, format: string = 'json') {
|
94 | if (object) console.log(format === 'yaml' ? yaml.safeDump(object, { lineWidth: 120 }) : JSON.stringify(object, null, ' '))
|
95 | }
|