Skip to content

Commit

Permalink
backup & restore (#251)
Browse files Browse the repository at this point in the history
* backup & restore

* refactor

* refactor

* back up key file

* fix messages

* update CHANGELOG

* update CHANGELOG
  • Loading branch information
shimataro committed Oct 10, 2023
1 parent 2983fc4 commit 31d4b8b
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

### Others

* back up and restore files when exist (thanks [@bambeusz](https://github.com/bambeusz))
* remove `macos-10.15` and `ubuntu-18.04` virtual environment

## [2.5.1] - 2023-03-25
Expand Down
83 changes: 78 additions & 5 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2738,6 +2738,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
const fs_1 = __importDefault(__nccwpck_require__(147));
const path_1 = __importDefault(__nccwpck_require__(17));
const core = __importStar(__nccwpck_require__(186));
const STATE_BACKUP_SUFFIX = "backup-suffix";
const KNOWN_HOSTS = [
"github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=",
];
Expand Down Expand Up @@ -2778,6 +2779,7 @@ function setPost() {
* setup function
*/
function setup() {
const backupSuffix = generateBackupSuffix();
// parameters
const key = core.getInput("key", {
required: true,
Expand All @@ -2799,6 +2801,7 @@ function setup() {
mode: 0o644,
flag: "a",
},
mustNotExist: false,
},
];
if (shouldCreateKeyFile(path_1.default.join(sshDirName, name), ifKeyExists)) {
Expand All @@ -2809,6 +2812,7 @@ function setup() {
mode: 0o400,
flag: "wx",
},
mustNotExist: true,
});
}
if (config !== "") {
Expand All @@ -2819,22 +2823,92 @@ function setup() {
mode: 0o644,
flag: "a",
},
mustNotExist: false,
});
}
// create files
const backedUpFileNames = [];
for (const file of files) {
const fileName = path_1.default.join(sshDirName, file.name);
if (backup(fileName, backupSuffix, file.mustNotExist)) {
backedUpFileNames.push(file.name);
}
fs_1.default.writeFileSync(fileName, file.contents, file.options);
}
console.log(`SSH key has been stored to ${sshDirName} successfully.`);
if (backedUpFileNames.length > 0) {
console.log(`Following files are backed up in suffix "${backupSuffix}"; ${backedUpFileNames.join(", ")}.`);
}
}
/**
* cleanup function
*/
function cleanup() {
// remove ".ssh" directory
const sshDirName = removeSshDirectory();
console.log(`SSH key in ${sshDirName} has been removed successfully.`);
const backupSuffix = core.getState(STATE_BACKUP_SUFFIX);
if (backupSuffix === "") {
// remove ".ssh" directory if suffix is not set
const sshDirName = removeSshDirectory();
console.log(`SSH key in ${sshDirName} has been removed successfully.`);
}
else {
restore(backupSuffix);
}
}
/**
* generate backup suffix name
* @returns backup suffix
*/
function generateBackupSuffix() {
const dirName = getSshDirectory();
if (!fs_1.default.existsSync(dirName)) {
// do nothing if .ssh does not exist
return "";
}
const backupSuffix = `.bak-${Date.now()}`;
core.saveState(STATE_BACKUP_SUFFIX, backupSuffix);
return backupSuffix;
}
/**
* back up file
* @param fileName file to back up
* @param backupSuffix suffix
* @param removeOrig remove original file
* @returns is file backed up?
*/
function backup(fileName, backupSuffix, removeOrig) {
if (backupSuffix === "") {
return false;
}
if (!fs_1.default.existsSync(fileName)) {
return false;
}
// move -> copy (in order to keep permissions when restore)
const fileNameBak = `${fileName}${backupSuffix}`;
fs_1.default.renameSync(fileName, fileNameBak);
if (!removeOrig) {
fs_1.default.copyFileSync(fileNameBak, fileName);
}
return true;
}
/**
* restore files
* @param backupSuffix suffix of backup directory
*/
function restore(backupSuffix) {
const dirName = getSshDirectory();
const keyFileName = core.getInput("name");
const restoredFileNames = [];
for (const fileName of ["known_hosts", "config", keyFileName]) {
const pathNameOrg = path_1.default.join(dirName, fileName);
const pathNameBak = `${pathNameOrg}${backupSuffix}`;
if (!fs_1.default.existsSync(pathNameBak)) {
continue;
}
fs_1.default.rmSync(pathNameOrg);
fs_1.default.renameSync(pathNameBak, pathNameOrg);
restoredFileNames.push(fileName);
}
console.log(`Following files in suffix "${backupSuffix}" are restored; ${restoredFileNames.join(", ")}`);
}
/**
* create ".ssh" directory
Expand Down Expand Up @@ -2929,8 +3003,7 @@ function shouldCreateKeyFile(keyFilePath, ifKeyExists) {
}
switch (ifKeyExists) {
case "replace":
// remove file and should create if replace
fs_1.default.unlinkSync(keyFilePath);
// should create if replace (existing file will be backed up when creating)
return true;
case "ignore":
// should NOT create if ignore
Expand Down
95 changes: 90 additions & 5 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ interface FileInfo {
name: string;
contents: string;
options: fs.WriteFileOptions;
mustNotExist: boolean; // file must not exist when creating
}

const STATE_BACKUP_SUFFIX = "backup-suffix";

const KNOWN_HOSTS = [
"github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=",
];
Expand Down Expand Up @@ -52,6 +55,8 @@ function setPost(): void {
* setup function
*/
function setup(): void {
const backupSuffix = generateBackupSuffix();

// parameters
const key = core.getInput("key", {
required: true,
Expand All @@ -75,6 +80,7 @@ function setup(): void {
mode: 0o644,
flag: "a",
},
mustNotExist: false,
},
];
if (shouldCreateKeyFile(path.join(sshDirName, name), ifKeyExists)) {
Expand All @@ -85,6 +91,7 @@ function setup(): void {
mode: 0o400,
flag: "wx",
},
mustNotExist: true,
});
}
if (config !== "") {
Expand All @@ -95,26 +102,105 @@ function setup(): void {
mode: 0o644,
flag: "a",
},
mustNotExist: false,
});
}

// create files
const backedUpFileNames: string[] = [];
for (const file of files) {
const fileName = path.join(sshDirName, file.name);
if (backup(fileName, backupSuffix, file.mustNotExist)) {
backedUpFileNames.push(file.name);
}

fs.writeFileSync(fileName, file.contents, file.options);
}

console.log(`SSH key has been stored to ${sshDirName} successfully.`);
if (backedUpFileNames.length > 0) {
console.log(`Following files are backed up in suffix "${backupSuffix}"; ${backedUpFileNames.join(", ")}.`);
}
}

/**
* cleanup function
*/
function cleanup(): void {
// remove ".ssh" directory
const sshDirName = removeSshDirectory();
const backupSuffix = core.getState(STATE_BACKUP_SUFFIX);
if (backupSuffix === "") {
// remove ".ssh" directory if suffix is not set
const sshDirName = removeSshDirectory();

console.log(`SSH key in ${sshDirName} has been removed successfully.`);
} else {
restore(backupSuffix);
}
}

/**
* generate backup suffix name
* @returns backup suffix
*/
function generateBackupSuffix(): string {
const dirName = getSshDirectory();
if (!fs.existsSync(dirName)) {
// do nothing if .ssh does not exist
return "";
}

const backupSuffix = `.bak-${Date.now()}`;
core.saveState(STATE_BACKUP_SUFFIX, backupSuffix);
return backupSuffix;
}

console.log(`SSH key in ${sshDirName} has been removed successfully.`);
/**
* back up file
* @param fileName file to back up
* @param backupSuffix suffix
* @param removeOrig remove original file
* @returns is file backed up?
*/
function backup(fileName: string, backupSuffix: string, removeOrig: boolean): boolean {
if (backupSuffix === "") {
return false;
}
if (!fs.existsSync(fileName)) {
return false;
}

// move -> copy (in order to keep permissions when restore)
const fileNameBak = `${fileName}${backupSuffix}`;
fs.renameSync(fileName, fileNameBak);
if (!removeOrig) {
fs.copyFileSync(fileNameBak, fileName);
}

return true;
}

/**
* restore files
* @param backupSuffix suffix of backup directory
*/
function restore(backupSuffix: string): void {
const dirName = getSshDirectory();
const keyFileName = core.getInput("name");

const restoredFileNames: string[] = [];
for (const fileName of ["known_hosts", "config", keyFileName]) {
const pathNameOrg = path.join(dirName, fileName);
const pathNameBak = `${pathNameOrg}${backupSuffix}`;

if (!fs.existsSync(pathNameBak)) {
continue;
}

fs.rmSync(pathNameOrg);
fs.renameSync(pathNameBak, pathNameOrg);
restoredFileNames.push(fileName);
}
console.log(`Following files in suffix "${backupSuffix}" are restored; ${restoredFileNames.join(", ")}`);
}

/**
Expand Down Expand Up @@ -222,8 +308,7 @@ function shouldCreateKeyFile(keyFilePath: string, ifKeyExists: string): boolean

switch (ifKeyExists) {
case "replace":
// remove file and should create if replace
fs.unlinkSync(keyFilePath);
// should create if replace (existing file will be backed up when creating)
return true;

case "ignore":
Expand Down

0 comments on commit 31d4b8b

Please sign in to comment.