-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
190 lines (166 loc) · 4.98 KB
/
index.js
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
require('dotenv').config();
const express = require("express")
const node_ssh = require("node-ssh")
const body_parser = require("body-parser")
const morgan = require("morgan")
const app = express();
const logger = morgan('dev');
app.use(body_parser.json())
app.use(logger);
app.get("/", (req, res) => {
const projects = require("./config")
res.status(200).json(projects)
return
})
app.post("/webhook", async (req, res, next) => {
const { ref, repository } = req.body;
if (!repository) {
res.status(200).json({
"message": "respository not present"
})
return;
}
const { name } = repository;
const ownerName = repository.owner.name;
const configuration = require("./config")[name]
// load configuration from config.js and check that
// a config exists for this repository. If the repository
// name is 'artscilab' then the 'artscilab' key must be present
// at the top level of the configuration object.
if (!configuration) {
res.status(404).json({
"message": `configuration for "${name}" not found`
})
return
}
if (!ref) {
res.status(200).json({
"message": "ref not present"
})
return;
}
if (!name) {
res.status(200).json({
"message": "repository name not present"
})
return;
}
if (!ownerName) {
res.status(200).json({
"message": "owner name not present"
})
return;
}
// Get the branch that this push came from and check that options
// for that branchname exists in the configuration for this repo.
// If the repo is 'artscilab' and we want to deploy on push to the
// 'master' branch, then the 'master' key must exist in
// the configuration object for 'artscilab'
const branchName = ref.split("/").pop();
const branchConfig = configuration[branchName];
if (!branchConfig) {
res.status(200).json({
"message": `configuration for branch "${branchName}" not found`
})
return
}
// The configuration for a branch must include the 'deployPath'
// key, which should specify the folder in which the code
// will be cloned into.
const { deployPath } = branchConfig;
if (!deployPath) {
res.status(200).json({
"message": `invalid configuration for branch "${branchName}"`
})
return;
}
const ssh = new node_ssh();
// connect to the server using the SSH client and private key
// from the environment variable.
// If deployMode == "git", it will use "git pull" command
// to bring in the latest changes
// if deployMode is "manual" or unset, it will use
// github api to copy files.
const { deployMode = "manual" } = branchConfig;
try {
await ssh.connect({
host: "atec.io",
username: "git",
privateKey: process.env.SSH_KEY
});
} catch (e) {
console.log(`Error on connect: ${e}`);
res.status(500).json({
"message": "couldn't connect to atec.io"
})
return
}
if (deployMode === "manual") {
// remove all existing files in the directory and
// download it fresh from github. Use to remove reliance
// on git on the server in the deployPath.
try {
const downloadUrl = `https://github.com/${ownerName}/${name}/archive/${branchName}.tar.gz`
const downloadCommand = `rm -r *; curl -SL ${downloadUrl} -o repo.tar.gz && tar xvzf repo.tar.gz --strip-components=1 && rm repo.tar.gz`;
console.log(`running download command: ${downloadCommand}`)
await ssh.execCommand(downloadCommand, {
cwd: deployPath
})
} catch(e) {
console.log(`Error on deploy: ${e}`)
res.status(500).json({
"message": "error running git pull"
})
return
}
}
else if (deployMode === "git") {
// run the "git pull" command to bring in the latest changes
// meaning the deployPath must already be a github repo
try {
const cloneCommand = `git pull`;
console.log(`running ${cloneCommand} in ${deployPath}`);
await ssh.execCommand(cloneCommand, {
cwd: deployPath
})
} catch(e) {
console.log(`Error on deploy: ${e}`)
res.status(500).json({
"message": "error running git pull"
})
return
}
}
else {
res.status(500).json({
"message": "Invalid deployMode"
})
return
}
const successMessage = `successfully deployed ${name}:${branchName} to ${deployPath}`
// Run all post-deploy commands from config
const { commands } = branchConfig;
if (commands === undefined) {
return res.json({
"message": successMessage
})
}
const { post: command } = commands;
if (command === undefined) {
return res.json({
"message": successMessage
})
}
console.log(`Running post deploy command ${command}`)
ssh.execCommand(command, {
cwd: deployPath
}).then((e) => {
console.log(`Successfully ran post deploy command '${command}'`)
}).catch((e) => {
console.error(`Failed running command: ${command}`, e)
})
res.json({
"message": successMessage
})
})
app.listen(process.env.PORT || 8080);