Merge pull request #265 from SamKirkland/v4.3.0-beta

Version 4.3.0
This commit is contained in:
Sam Kirkland 2022-02-19 15:06:06 -06:00 committed by GitHub
commit d0aa838726
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 2208 additions and 93 deletions

View File

@ -23,7 +23,7 @@ jobs:
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: 📂 Sync files - name: 📂 Sync files
uses: SamKirkland/FTP-Deploy-Action@4.2.0 uses: SamKirkland/FTP-Deploy-Action@4.3.0
with: with:
server: ftp.samkirkland.com server: ftp.samkirkland.com
username: myFtpUserName username: myFtpUserName
@ -98,7 +98,7 @@ jobs:
npm run build npm run build
- name: 📂 Sync files - name: 📂 Sync files
uses: SamKirkland/FTP-Deploy-Action@4.2.0 uses: SamKirkland/FTP-Deploy-Action@4.3.0
with: with:
server: ftp.samkirkland.com server: ftp.samkirkland.com
username: myFtpUserName username: myFtpUserName
@ -118,7 +118,7 @@ jobs:
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: 📂 Sync files - name: 📂 Sync files
uses: SamKirkland/FTP-Deploy-Action@4.2.0 uses: SamKirkland/FTP-Deploy-Action@4.3.0
with: with:
server: ftp.samkirkland.com server: ftp.samkirkland.com
username: myFtpUserName username: myFtpUserName
@ -141,7 +141,7 @@ jobs:
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: 📂 Sync files - name: 📂 Sync files
uses: SamKirkland/FTP-Deploy-Action@4.2.0 uses: SamKirkland/FTP-Deploy-Action@4.3.0
with: with:
server: ftp.samkirkland.com server: ftp.samkirkland.com
username: myFtpUserName username: myFtpUserName
@ -163,7 +163,7 @@ jobs:
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: 📂 Sync files - name: 📂 Sync files
uses: SamKirkland/FTP-Deploy-Action@4.2.0 uses: SamKirkland/FTP-Deploy-Action@4.3.0
with: with:
server: ftp.samkirkland.com server: ftp.samkirkland.com
username: myFtpUserName username: myFtpUserName

130
dist/index.js vendored
View File

@ -2544,9 +2544,6 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.HashDiff = exports.fileHash = void 0; exports.HashDiff = exports.fileHash = void 0;
const fs_1 = __importDefault(__nccwpck_require__(5747)); const fs_1 = __importDefault(__nccwpck_require__(5747));
const crypto_1 = __importDefault(__nccwpck_require__(6417)); const crypto_1 = __importDefault(__nccwpck_require__(6417));
function formatNumber(number) {
return number.toLocaleString();
}
function fileHash(filename, algorithm) { function fileHash(filename, algorithm) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -2575,23 +2572,18 @@ function fileHash(filename, algorithm) {
} }
exports.fileHash = fileHash; exports.fileHash = fileHash;
class HashDiff { class HashDiff {
getDiffs(localFiles, serverFiles, logger) { getDiffs(localFiles, serverFiles) {
var _a, _b, _c; var _a, _b, _c;
const uploadList = []; const uploadList = [];
const deleteList = []; const deleteList = [];
const replaceList = []; const replaceList = [];
const sameList = [];
let sizeUpload = 0; let sizeUpload = 0;
let sizeDelete = 0; let sizeDelete = 0;
let sizeReplace = 0; let sizeReplace = 0;
// alphabetize each list based off path // alphabetize each list based off path
const localFilesSorted = localFiles.data.sort((first, second) => first.name.localeCompare(second.name)); const localFilesSorted = localFiles.data.sort((first, second) => first.name.localeCompare(second.name));
const serverFilesSorted = serverFiles.data.sort((first, second) => first.name.localeCompare(second.name)); const serverFilesSorted = serverFiles.data.sort((first, second) => first.name.localeCompare(second.name));
logger.standard(`----------------------------------------------------------------`);
logger.standard(`Local Files:\t${formatNumber(localFilesSorted.length)}`);
logger.standard(`Server Files:\t${formatNumber(localFilesSorted.length)}`);
logger.standard(`----------------------------------------------------------------`);
logger.standard(`Calculating differences between client & server`);
logger.standard(`----------------------------------------------------------------`);
let localPosition = 0; let localPosition = 0;
let serverPosition = 0; let serverPosition = 0;
while (localPosition + serverPosition < localFilesSorted.length + serverFilesSorted.length) { while (localPosition + serverPosition < localFilesSorted.length + serverFilesSorted.length) {
@ -2608,15 +2600,11 @@ class HashDiff {
fileNameCompare = localFile.name.localeCompare(serverFile.name); fileNameCompare = localFile.name.localeCompare(serverFile.name);
} }
if (fileNameCompare < 0) { if (fileNameCompare < 0) {
let icon = localFile.type === "folder" ? `📁 Create` : ` Upload`;
logger.standard(`${icon}: ${localFile.name}`);
uploadList.push(localFile); uploadList.push(localFile);
sizeUpload += (_a = localFile.size) !== null && _a !== void 0 ? _a : 0; sizeUpload += (_a = localFile.size) !== null && _a !== void 0 ? _a : 0;
localPosition += 1; localPosition += 1;
} }
else if (fileNameCompare > 0) { else if (fileNameCompare > 0) {
let icon = serverFile.type === "folder" ? `📁` : `🗑️`;
logger.standard(`${icon} Delete: ${serverFile.name} `);
deleteList.push(serverFile); deleteList.push(serverFile);
sizeDelete += (_b = serverFile.size) !== null && _b !== void 0 ? _b : 0; sizeDelete += (_b = serverFile.size) !== null && _b !== void 0 ? _b : 0;
serverPosition += 1; serverPosition += 1;
@ -2625,10 +2613,9 @@ class HashDiff {
// paths are a match // paths are a match
if (localFile.type === "file" && serverFile.type === "file") { if (localFile.type === "file" && serverFile.type === "file") {
if (localFile.hash === serverFile.hash) { if (localFile.hash === serverFile.hash) {
logger.standard(`⚖️ File content is the same, doing nothing: ${localFile.name}`); sameList.push(localFile);
} }
else { else {
logger.standard(`🔁 File replace: ${localFile.name}`);
sizeReplace += (_c = localFile.size) !== null && _c !== void 0 ? _c : 0; sizeReplace += (_c = localFile.size) !== null && _c !== void 0 ? _c : 0;
replaceList.push(localFile); replaceList.push(localFile);
} }
@ -2637,10 +2624,26 @@ class HashDiff {
serverPosition += 1; serverPosition += 1;
} }
} }
// optimize modifications
let foldersToDelete = deleteList.filter((item) => item.type === "folder");
// remove files/folders that have a nested parent folder we plan on deleting
const optimizedDeleteList = deleteList.filter((itemToDelete) => {
const parentFolderIsBeingDeleted = foldersToDelete.find((folder) => {
const isSameFile = itemToDelete.name === folder.name;
const parentFolderExists = itemToDelete.name.startsWith(folder.name);
return parentFolderExists && !isSameFile;
}) !== undefined;
if (parentFolderIsBeingDeleted) {
// a parent folder is being deleted, no need to delete this one
return false;
}
return true;
});
return { return {
upload: uploadList, upload: uploadList,
delete: deleteList, delete: optimizedDeleteList,
replace: replaceList, replace: replaceList,
same: sameList,
sizeDelete, sizeDelete,
sizeReplace, sizeReplace,
sizeUpload sizeUpload
@ -2764,6 +2767,11 @@ function getServerFiles(client, logger, timings, args) {
const serverFiles = yield downloadFileList(client, logger, args["state-name"]); const serverFiles = yield downloadFileList(client, logger, args["state-name"]);
logger.all(`----------------------------------------------------------------`); logger.all(`----------------------------------------------------------------`);
logger.all(`Last published on 📅 ${new Date(serverFiles.generatedTime).toLocaleDateString(undefined, { weekday: "long", year: "numeric", month: "long", day: "numeric", hour: "numeric", minute: "numeric" })}`); logger.all(`Last published on 📅 ${new Date(serverFiles.generatedTime).toLocaleDateString(undefined, { weekday: "long", year: "numeric", month: "long", day: "numeric", hour: "numeric", minute: "numeric" })}`);
// apply exclude options to server
if (args.exclude.length > 0) {
const filteredData = serverFiles.data.filter((item) => utilities_1.applyExcludeFilter({ path: item.name, isDirectory: () => item.type === "folder" }, args.exclude));
serverFiles.data = filteredData;
}
return serverFiles; return serverFiles;
} }
catch (error) { catch (error) {
@ -2810,7 +2818,33 @@ function deploy(args, logger, timings) {
const serverFiles = yield getServerFiles(client, logger, timings, args); const serverFiles = yield getServerFiles(client, logger, timings, args);
timings.start("logging"); timings.start("logging");
const diffTool = new HashDiff_1.HashDiff(); const diffTool = new HashDiff_1.HashDiff();
const diffs = diffTool.getDiffs(localFiles, serverFiles, logger); logger.standard(`----------------------------------------------------------------`);
logger.standard(`Local Files:\t${utilities_1.formatNumber(localFiles.data.length)}`);
logger.standard(`Server Files:\t${utilities_1.formatNumber(serverFiles.data.length)}`);
logger.standard(`----------------------------------------------------------------`);
logger.standard(`Calculating differences between client & server`);
logger.standard(`----------------------------------------------------------------`);
const diffs = diffTool.getDiffs(localFiles, serverFiles);
diffs.upload.filter((itemUpload) => itemUpload.type === "folder").map((itemUpload) => {
logger.standard(`📁 Create: ${itemUpload.name}`);
});
diffs.upload.filter((itemUpload) => itemUpload.type === "file").map((itemUpload) => {
logger.standard(`📄 Upload: ${itemUpload.name}`);
});
diffs.replace.map((itemReplace) => {
logger.standard(`🔁 File replace: ${itemReplace.name}`);
});
diffs.delete.filter((itemUpload) => itemUpload.type === "file").map((itemDelete) => {
logger.standard(`📄 Delete: ${itemDelete.name} `);
});
diffs.delete.filter((itemUpload) => itemUpload.type === "folder").map((itemDelete) => {
logger.standard(`📁 Delete: ${itemDelete.name} `);
});
diffs.same.map((itemSame) => {
if (itemSame.type === "file") {
logger.standard(`⚖️ File content is the same, doing nothing: ${itemSame.name}`);
}
});
timings.stop("logging"); timings.stop("logging");
totalBytesUploaded = diffs.sizeUpload + diffs.sizeReplace; totalBytesUploaded = diffs.sizeUpload + diffs.sizeReplace;
timings.start("upload"); timings.start("upload");
@ -2927,26 +2961,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod }; return (mod && mod.__esModule) ? mod : { "default": mod };
}; };
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.getLocalFiles = exports.applyExcludeFilter = void 0; exports.getLocalFiles = void 0;
const readdir_enhanced_1 = __importDefault(__nccwpck_require__(8811)); const readdir_enhanced_1 = __importDefault(__nccwpck_require__(8811));
const types_1 = __nccwpck_require__(6703); const types_1 = __nccwpck_require__(6703);
const HashDiff_1 = __nccwpck_require__(9946); const HashDiff_1 = __nccwpck_require__(9946);
const multimatch_1 = __importDefault(__nccwpck_require__(8222)); const utilities_1 = __nccwpck_require__(4389);
function applyExcludeFilter(stat, excludeFilter) {
// match exclude, return immediatley
if (excludeFilter.length > 0) {
const pathWithFolderSlash = stat.path + (stat.isDirectory() ? "/" : "");
const excludeMatch = multimatch_1.default(pathWithFolderSlash, excludeFilter, { matchBase: true, dot: true });
if (excludeMatch.length > 0) {
return false;
}
}
return true;
}
exports.applyExcludeFilter = applyExcludeFilter;
function getLocalFiles(args) { function getLocalFiles(args) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const files = yield readdir_enhanced_1.default.async(args["local-dir"], { deep: true, stats: true, sep: "/", filter: (stat) => applyExcludeFilter(stat, args.exclude) }); const files = yield readdir_enhanced_1.default.async(args["local-dir"], { deep: true, stats: true, sep: "/", filter: (stat) => utilities_1.applyExcludeFilter(stat, args.exclude) });
const records = []; const records = [];
for (let stat of files) { for (let stat of files) {
if (stat.isDirectory()) { if (stat.isDirectory()) {
@ -3138,22 +3160,12 @@ class FTPSyncProvider {
}); });
} }
removeFolder(folderPath) { removeFolder(folderPath) {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
this.logger.all(`removing folder "${folderPath + "/"}"`); const absoluteFolderPath = "/" + (this.serverPath.startsWith("./") ? this.serverPath.replace("./", "") : this.serverPath) + folderPath;
const path = this.getFileBreadcrumbs(folderPath + "/"); this.logger.all(`removing folder "${absoluteFolderPath}"`);
if (path.folders === null) {
this.logger.verbose(` no need to change dir`);
}
else {
const relativeFolderPath = path.folders[((_a = path.folders) === null || _a === void 0 ? void 0 : _a.length) - 1] + "/";
this.logger.verbose(` removing folder "${relativeFolderPath}"`);
if (this.dryRun === false) { if (this.dryRun === false) {
yield utilities_1.retryRequest(this.logger, () => __awaiter(this, void 0, void 0, function* () { return yield this.client.removeDir(relativeFolderPath); })); yield utilities_1.retryRequest(this.logger, () => __awaiter(this, void 0, void 0, function* () { return yield this.client.removeDir(absoluteFolderPath); }));
} }
}
// navigate back to the root folder
yield this.upDir((_b = path.folders) === null || _b === void 0 ? void 0 : _b.length);
this.logger.verbose(` completed`); this.logger.verbose(` completed`);
}); });
} }
@ -3304,10 +3316,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod }; return (mod && mod.__esModule) ? mod : { "default": mod };
}; };
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.getDefaultSettings = exports.Timer = exports.Timings = exports.retryRequest = exports.pluralize = exports.Logger = void 0; exports.applyExcludeFilter = exports.getDefaultSettings = exports.Timer = exports.Timings = exports.retryRequest = exports.formatNumber = exports.pluralize = exports.Logger = void 0;
const pretty_ms_1 = __importDefault(__nccwpck_require__(1127)); const pretty_ms_1 = __importDefault(__nccwpck_require__(1127));
const module_1 = __nccwpck_require__(8347); const module_1 = __nccwpck_require__(8347);
const types_1 = __nccwpck_require__(6703); const types_1 = __nccwpck_require__(6703);
const multimatch_1 = __importDefault(__nccwpck_require__(8222));
class Logger { class Logger {
constructor(level) { constructor(level) {
this.level = level; this.level = level;
@ -3336,6 +3349,10 @@ function pluralize(count, singular, plural) {
return plural; return plural;
} }
exports.pluralize = pluralize; exports.pluralize = pluralize;
function formatNumber(number) {
return number.toLocaleString();
}
exports.formatNumber = formatNumber;
/** /**
* retry a request * retry a request
* *
@ -3452,6 +3469,19 @@ function getDefaultSettings(withoutDefaults) {
}; };
} }
exports.getDefaultSettings = getDefaultSettings; exports.getDefaultSettings = getDefaultSettings;
function applyExcludeFilter(stat, excludeFilters) {
// match exclude, return immediatley
if (excludeFilters.length > 0) {
// todo this could be a performance problem...
const pathWithFolderSlash = stat.path + (stat.isDirectory() ? "/" : "");
const excludeMatch = multimatch_1.default(pathWithFolderSlash, excludeFilters, { matchBase: true, dot: true });
if (excludeMatch.length > 0) {
return false;
}
}
return true;
}
exports.applyExcludeFilter = applyExcludeFilter;
/***/ }), /***/ }),
@ -7954,12 +7984,12 @@ function optionalInt(argumentName, rawValue) {
} }
exports.optionalInt = optionalInt; exports.optionalInt = optionalInt;
function optionalStringArray(argumentName, rawValue) { function optionalStringArray(argumentName, rawValue) {
if (typeof rawValue === "string") {
throw new Error(`${argumentName}: invalid parameter - you provided "${rawValue}". This option expects an list in the EXACT format described in the readme`);
}
if (rawValue.length === 0) { if (rawValue.length === 0) {
return undefined; return undefined;
} }
if (typeof rawValue === "string") {
throw new Error(`${argumentName}: invalid parameter - you provided "${rawValue}". This option expects an list in the EXACT format described in the readme`);
}
return rawValue; return rawValue;
} }
exports.optionalStringArray = optionalStringArray; exports.optionalStringArray = optionalStringArray;

2149
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "ftp-deploy-action", "name": "ftp-deploy-action",
"version": "4.2.0", "version": "4.3.0",
"private": true, "private": true,
"description": "Automate deploying websites and more with this GitHub action", "description": "Automate deploying websites and more with this GitHub action",
"main": "dist/index.js", "main": "dist/index.js",
@ -23,7 +23,7 @@
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/core": "^1.6.0", "@actions/core": "^1.6.0",
"@samkirkland/ftp-deploy": "^1.1.1", "@samkirkland/ftp-deploy": "^1.2.1",
"@types/jest": "^27.0.2", "@types/jest": "^27.0.2",
"jest": "^27.2.5", "jest": "^27.2.5",
"ts-jest": "^27.0.5", "ts-jest": "^27.0.5",

View File

@ -91,6 +91,10 @@ export function optionalInt(argumentName: string, rawValue: string): number | un
} }
export function optionalStringArray(argumentName: string, rawValue: string[]): string[] | undefined { export function optionalStringArray(argumentName: string, rawValue: string[]): string[] | undefined {
if (rawValue.length === 0) {
return undefined;
}
if (typeof rawValue === "string") { if (typeof rawValue === "string") {
throw new Error(`${argumentName}: invalid parameter - you provided "${rawValue}". This option expects an list in the EXACT format described in the readme`); throw new Error(`${argumentName}: invalid parameter - you provided "${rawValue}". This option expects an list in the EXACT format described in the readme`);
} }