-
Notifications
You must be signed in to change notification settings - Fork 41
/
index.js
149 lines (121 loc) · 4.57 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
const core = require('@actions/core');
const exec = require('@actions/exec');
const path = require('path');
function wait(seconds) {
return new Promise(resolve => {
if ((typeof seconds) !== 'number') {
throw new Error('seconds not a number');
}
core.info(`Waiting ${seconds} seconds...`);
setTimeout(() => resolve("done!"), seconds * 1000)
});
}
async function isNextReleaseHealthy(release, app) {
let releasesOutput = '';
const options = {
listeners: {
stdout: data => {
releasesOutput += data.toString();
}
}
};
await core.group("Getting current replicas", async () => {
await exec.exec(`gigalixir ps -a ${app}`, [], options);
});
const releases = JSON.parse(releasesOutput);
return releases.pods.filter((pod) => (Number(pod.version) === release && pod.status === "Healthy")).length >= releases.replicas_desired;
}
async function waitForNewRelease(oldRelease, app, attempts) {
const maxAttempts = 60;
if (await isNextReleaseHealthy(oldRelease + 1, app)) {
return await Promise.resolve(true);
} else {
if (attempts <= maxAttempts) {
await wait(10);
await waitForNewRelease(oldRelease, app, attempts + 1);
} else {
throw "Taking too long for new release to deploy";
}
}
}
async function getCurrentRelease(app) {
let releasesOutput = '';
const options = {
listeners: {
stdout: data => {
releasesOutput += data.toString();
}
}
};
await core.group("Getting current release", async () => {
await exec.exec(`gigalixir releases -a ${app}`, [], options);
});
const releases = JSON.parse(releasesOutput);
const currentRelease = releases.length ? Number(releases[0].version) : 0;
return currentRelease;
}
function formatReleaseMessage(releaseNumber) {
return releaseNumber ?
`The current release is ${releaseNumber}` :
"This is the first release";
}
function addExtraFlagCleanCache(gigalixirClean) {
return (gigalixirClean === "true") ? ` -c http.extraheader="GIGALIXIR-CLEAN: true" ` : ""
}
async function run() {
try {
const appSubfolder = core.getInput('APP_SUBFOLDER', {required: false});
const gigalixirApp = core.getInput('GIGALIXIR_APP', {required: true});
const gigalixirClean = core.getInput('GIGALIXIR_CLEAN', {required: false});
const gigalixirUsername = core.getInput('GIGALIXIR_USERNAME', {required: true});
const gigalixirPassword = core.getInput('GIGALIXIR_PASSWORD', {required: true});
const migrations = core.getInput('MIGRATIONS', {required: true});
const sshPrivateKey = core.getInput('SSH_PRIVATE_KEY', {required: JSON.parse(migrations)});
await core.group("Installing gigalixir", async () => {
await exec.exec('pip3 install gigalixir')
});
await core.group("Logging in to gigalixir", async () => {
await exec.exec(`gigalixir login -e "${gigalixirUsername}" -y -p "${gigalixirPassword}"`)
});
await core.group("Setting git remote for gigalixir", async () => {
await exec.exec(`gigalixir git:remote ${gigalixirApp}`);
});
const currentRelease = await core.group("Getting current release", async () => {
return await getCurrentRelease(gigalixirApp);
});
core.info(formatReleaseMessage(currentRelease));
await core.group("Deploying to gigalixir", async () => {
if (appSubfolder) {
await exec.exec(`git ${addExtraFlagCleanCache(gigalixirClean)} subtree push --prefix ${appSubfolder} gigalixir master`);
} else {
await exec.exec(`git ${addExtraFlagCleanCache(gigalixirClean)} push -f gigalixir HEAD:refs/heads/master`);
}
});
if (migrations === "true") {
await core.group("Adding private key to gigalixir", async () => {
await exec.exec(path.join(__dirname, "../bin/add-private-key"), [sshPrivateKey]);
});
await core.group("Waiting for new release to deploy", async () => {
await waitForNewRelease(currentRelease, gigalixirApp, 1);
});
try {
await core.group("Running migrations", async () => {
await exec.exec(`gigalixir ps:migrate -a ${gigalixirApp}`)
});
} catch (error) {
if (currentRelease === 0) {
core.warning("Migration failed");
} else {
core.warning(`Migration failed, rolling back to the previous release: ${currentRelease}`);
await core.group("Rolling back", async () => {
await exec.exec(`gigalixir releases:rollback -a ${gigalixirApp}`)
});
}
core.setFailed(error.message);
}
}
} catch (error) {
core.setFailed(error.message);
}
}
run();