1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
package config
import (
"path"
"gerrit.wikimedia.org/r/blubber/build"
)
// NodeConfig holds configuration fields related to the Node environment and
// whether/how to install NPM packages.
//
type NodeConfig struct {
Requirements []string `yaml:"requirements"` // install requirements from given files
Env string `yaml:"env" validate:"omitempty,nodeenv"` // environment name ("production" install)
}
// Merge takes another NodeConfig and merges its fields into this one's,
// overwriting both the environment and requirements files.
//
func (nc *NodeConfig) Merge(nc2 NodeConfig) {
if nc2.Requirements != nil {
nc.Requirements = nc2.Requirements
}
if nc2.Env != "" {
nc.Env = nc2.Env
}
}
// InstructionsForPhase injects instructions into the build related to Node
// dependency installation and setting of the NODE_ENV, NODE_PATH, and PATH
// environment variables.
//
// PhasePreInstall
//
// Installs Node package dependencies declared in requirements files into the
// shared library directory (/opt/lib). Only production related packages are
// install if NodeConfig.Env is set to "production" in which case `npm dedupe`
// is also run. Installing dependencies during the build.PhasePreInstall phase
// allows a compiler implementation (e.g. Docker) to produce cache-efficient
// output so only changes to package.json will invalidate these steps of the
// image build.
//
// PhasePostInstall
//
// Injects build.Env instructions for NODE_ENV, NODE_PATH, and PATH, setting
// the environment according to the configuration, ensuring that packages
// installed during build.PhasePreInstall are found by Node, and that any
// installed binaries are found by shells.
//
func (nc NodeConfig) InstructionsForPhase(phase build.Phase) []build.Instruction {
switch phase {
case build.PhasePreInstall:
if len(nc.Requirements) > 0 {
npmInstall := build.RunAll{[]build.Run{
{"cd", []string{LocalLibPrefix}},
{"npm install", []string{}},
}}
if nc.Env == "production" {
npmInstall.Runs[1].Arguments = []string{"--production"}
npmInstall.Runs = append(npmInstall.Runs,
build.Run{"npm dedupe", []string{}},
)
}
return []build.Instruction{
build.Copy{nc.Requirements, LocalLibPrefix},
npmInstall,
}
}
case build.PhasePostInstall:
if nc.Env != "" || len(nc.Requirements) > 0 {
return []build.Instruction{build.Env{map[string]string{
"NODE_ENV": nc.Env,
"NODE_PATH": path.Join(LocalLibPrefix, "node_modules"),
"PATH": path.Join(LocalLibPrefix, "node_modules", ".bin") + ":${PATH}",
}}}
}
}
return []build.Instruction{}
}
|