-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
149 lines (136 loc) · 4.04 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
#!/usr/bin/env node
// sftp-upload upload files to an SFTP server.
// Copyright (C) 2020 Matthew Glazar
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
"use strict";
let SSH2SFTPClient = require("ssh2-sftp-client");
let actionsCore = require("@actions/core");
let assert = require("assert");
let fs = require("fs");
let glob = require("@actions/glob");
let path = require("path");
async function mainAsync() {
await uploadGlobsAsync({
host: getRequiredInput("host"),
localFileGlobs: getRequiredInput("local-file-globs").split("\n"),
privateKey: getRequiredInput("private-key"),
remoteDirectory: getRequiredInput("remote-directory"),
user: getRequiredInput("user"),
});
}
async function uploadGlobsAsync({ localFileGlobs, ...otherOptions }) {
let localFilesByGlob = await Promise.all(
localFileGlobs.map(async (pattern) => await globAsync(pattern))
);
let haveNonMatchingLocalFileGlobs = false;
for (let [patternIndex, files] of localFilesByGlob.entries()) {
if (files.length === 0) {
console.error(
`error: Pattern matched no files: ${localFileGlobs[patternIndex]}`
);
haveNonMatchingLocalFileGlobs = true;
}
}
if (haveNonMatchingLocalFileGlobs) {
process.exit(1);
}
let localFiles = removeDuplicates(localFilesByGlob.flat());
console.log(`note: Found ${localFiles.length} files to upload`);
await uploadFilesAsync({
localFiles: localFiles,
...otherOptions,
});
}
async function uploadFilesAsync({
host,
localFiles,
privateKey,
remoteDirectory,
user,
}) {
let client = new SSH2SFTPClient();
try {
await client.connect({
host: host,
username: user,
privateKey: privateKey,
});
console.log(`note: Uploading to remote directory: ${remoteDirectory}`);
await createDirectoryRecursiveIfNotExistsAsync(client, remoteDirectory);
for (let localFile of localFiles) {
console.log(`note: Uploading: ${localFile}`);
await client.put(
localFile,
path.posix.join(remoteDirectory, path.basename(localFile)),
{ mode: 0o644 }
);
}
} finally {
await client.end();
}
}
async function createDirectoryRecursiveIfNotExistsAsync(sftpClient, path) {
try {
await sftpClient.mkdir(path, /*recursive=*/ true);
} catch (mkdirError) {
try {
let stat = await sftpClient.stat(path);
if (stat.isDirectory) {
// mkdir failed because the directory already exists. Ignore.
} else {
// mkdir failed because the path refers to a non-directory.
throw mkdirError;
}
} catch (statError) {
// mkdir failed and the path does not exist.
throw mkdirError;
}
}
}
function getRequiredInput(name) {
let value = actionsCore.getInput(name);
if (value === "") {
throw new Error(`Missing required input: ${name}`);
}
return value;
}
async function globAsync(pattern) {
assert.strictEqual(
/\n/.test(pattern),
false,
`Pattern should not contain a newline character, but it does: ${pattern}`
);
return await (await glob.create(pattern)).glob();
}
function removeDuplicates(items) {
return [...new Set(items)];
}
if (typeof Array.prototype.flat !== "function") {
Array.prototype.flat = function flat() {
let result = [];
for (let items of this) {
result.push(...items);
}
return result;
};
}
mainAsync()
.then(() => {
process.exit(0);
})
.catch((error) => {
console.error(`error: ${error.stack}`);
process.exit(1);
});