-
Notifications
You must be signed in to change notification settings - Fork 649
Expand file tree
/
Copy pathdeployDigitalOcean.ts
More file actions
138 lines (123 loc) Β· 3.75 KB
/
deployDigitalOcean.ts
File metadata and controls
138 lines (123 loc) Β· 3.75 KB
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
import inquirer from "inquirer";
import got from "got";
import ora from "ora";
import chalk from "chalk";
import {
createDroplet,
Droplet,
DropletV4Network,
getDroplet,
} from "../lib/digitalOcean";
import waitUntil from "async-wait-until";
const getUserDataScript = async () =>
got(
"https://raw.githubusercontent.com/cdr/deploy-code-server/main/deploy-vm/launch-code-server.sh"
).text();
const isPermissionError = (error: unknown) => {
return error instanceof got.HTTPError && error.response.statusCode === 401;
};
const getPublicIp = (droplet: Droplet) => {
const network = droplet.networks.v4.find(
(network) => network.type === "public"
);
return network?.ip_address;
};
const isCodeServerLive = async (droplet: Droplet) => {
try {
const response = await got(`http://${getPublicIp(droplet)}`, { retry: 0 });
return response.statusCode === 200;
} catch {
return false;
}
};
const handleErrorLog = (error: unknown) => {
if (isPermissionError(error)) {
console.log(
chalk.red(
chalk.bold("Invalid token."),
"Please, verify your token and try again."
)
);
} else {
console.log(chalk.red.bold("Something wrong happened"));
console.log(
chalk.red(
"You may have to delete the droplet manually on your Digital Ocean dashboard."
)
);
}
};
const oneMinute = 1000 * 60;
const fiveMinutes = oneMinute * 5;
const waitUntilBeActive = (droplet: Droplet, token: string) => {
return waitUntil(
async () => {
const dropletInfo = await getDroplet({ token, id: droplet.id });
return dropletInfo.status === "active";
},
{ timeout: fiveMinutes, intervalBetweenAttempts: oneMinute / 2 }
);
};
const waitUntilHasPublicIp = (droplet: Droplet, token: string) => {
return waitUntil(
async () => {
const dropletInfo = await getDroplet({ token, id: droplet.id });
const ip = getPublicIp(dropletInfo);
return ip !== undefined;
},
{ timeout: fiveMinutes, intervalBetweenAttempts: oneMinute / 2 }
);
};
const waitUntilCodeServerIsLive = (droplet: Droplet, token: string) => {
return waitUntil(
async () => {
const dropletInfo = await getDroplet({ token, id: droplet.id });
return isCodeServerLive(dropletInfo);
},
{ timeout: fiveMinutes * 2, intervalBetweenAttempts: oneMinute / 2 }
);
};
export const deployDigitalOcean = async () => {
let spinner: ora.Ora;
console.log(
chalk.blue(
"You can create a token on",
chalk.bold("https://cloud.digitalocean.com/account/api/tokens")
)
);
const { token } = await inquirer.prompt([
{ name: "token", message: "Your Digital Ocean token:", type: "password" },
]);
try {
let spinner = ora("Creating droplet and installing code-server").start();
let droplet = await createDroplet({
userData: await getUserDataScript(),
token,
});
spinner.stop();
console.log(chalk.green("β
Droplet created"));
spinner = ora("Waiting droplet to be active").start();
await waitUntilBeActive(droplet, token);
spinner.stop();
console.log(chalk.green("β
Droplet active"));
spinner = ora("Waiting droplet to have a public IP").start();
await waitUntilHasPublicIp(droplet, token);
spinner.stop();
console.log(chalk.green("β
Public IP is available"));
spinner = ora(
"Waiting code-server to be live. It can take up to 5 minutes."
).start();
await waitUntilCodeServerIsLive(droplet, token);
droplet = await getDroplet({ token, id: droplet.id });
spinner.stop();
console.log(
chalk.green(
`π Your code-server is live. You can access it on`,
chalk.bold(`http://${getPublicIp(droplet)}`)
)
);
} catch (error) {
spinner.stop();
handleErrorLog(error);
}
};