"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.deploy = exports.init = void 0; const core_1 = require("@actions/core"); const io_1 = require("@actions/io"); const fs_1 = __importDefault(require("fs")); const constants_1 = require("./constants"); const execute_1 = require("./execute"); const worktree_1 = require("./worktree"); const util_1 = require("./util"); /* Initializes git in the workspace. */ function init(action) { return __awaiter(this, void 0, void 0, function* () { try { core_1.info(`Deploying using ${action.tokenType}… 🔑`); core_1.info('Configuring git…'); yield execute_1.execute(`git config user.name "${action.name}"`, action.workspace, action.silent); yield execute_1.execute(`git config user.email "${action.email}"`, action.workspace, action.silent); try { if ((process.env.CI && !action.sshKey) || action.isTest) { /* Ensures that previously set Git configs do not interfere with the deployment. Only runs in the GitHub Actions CI environment if a user is not using an SSH key. */ yield execute_1.execute(`git config --local --unset-all http.https://${action.hostname}/.extraheader`, action.workspace, action.silent); } if (action.isTest === constants_1.TestFlag.UNABLE_TO_UNSET_GIT_CONFIG) { throw new Error(); } } catch (_a) { core_1.info('Unable to unset previous git config authentication as it may not exist, continuing…'); } try { yield execute_1.execute(`git remote rm origin`, action.workspace, action.silent); if (action.isTest === constants_1.TestFlag.UNABLE_TO_REMOVE_ORIGIN) { throw new Error(); } } catch (_b) { core_1.info('Attempted to remove origin but failed, continuing…'); } yield execute_1.execute(`git remote add origin ${action.repositoryPath}`, action.workspace, action.silent); core_1.info('Git configured… 🔧'); } catch (error) { throw new Error(`There was an error initializing the repository: ${util_1.suppressSensitiveInformation(error.message, action)} ❌`); } }); } exports.init = init; /* Runs the necessary steps to make the deployment. */ function deploy(action) { return __awaiter(this, void 0, void 0, function* () { const temporaryDeploymentDirectory = 'github-pages-deploy-action-temp-deployment-folder'; const temporaryDeploymentBranch = `github-pages-deploy-action/${Math.random() .toString(36) .substr(2, 9)}`; core_1.info('Starting to commit changes…'); try { const commitMessage = !util_1.isNullOrUndefined(action.commitMessage) ? action.commitMessage : `Deploying to ${action.branch}${process.env.GITHUB_SHA ? ` from @ ${process.env.GITHUB_REPOSITORY}@${process.env.GITHUB_SHA}` : ''} 🚀`; // Checks to see if the remote exists prior to deploying. const branchExists = action.isTest & constants_1.TestFlag.HAS_REMOTE_BRANCH || (yield execute_1.execute(`git ls-remote --heads ${action.repositoryPath} refs/heads/${action.branch}`, action.workspace, action.silent)); yield worktree_1.generateWorktree(action, temporaryDeploymentDirectory, branchExists); // Ensures that items that need to be excluded from the clean job get parsed. let excludes = ''; if (action.clean && action.cleanExclude) { for (const item of action.cleanExclude) { excludes += `--exclude ${item} `; } } if (action.targetFolder) { core_1.info(`Creating target folder if it doesn't already exist… 📌`); yield io_1.mkdirP(`${temporaryDeploymentDirectory}/${action.targetFolder}`); } /* Pushes all of the build files into the deployment directory. Allows the user to specify the root if '.' is provided. rsync is used to prevent file duplication. */ yield execute_1.execute(`rsync -q -av --checksum --progress ${action.folderPath}/. ${action.targetFolder ? `${temporaryDeploymentDirectory}/${action.targetFolder}` : temporaryDeploymentDirectory} ${action.clean ? `--delete ${excludes} ${!fs_1.default.existsSync(`${action.folderPath}/CNAME`) ? '--exclude CNAME' : ''} ${!fs_1.default.existsSync(`${action.folderPath}/.nojekyll`) ? '--exclude .nojekyll' : ''}` : ''} --exclude .ssh --exclude .git --exclude .github ${action.folderPath === action.workspace ? `--exclude ${temporaryDeploymentDirectory}` : ''}`, action.workspace, action.silent); // Use git status to check if we have something to commit. // Special case is singleCommit with existing history, when // we're really interested if the diff against the upstream branch // changed. const checkGitStatus = branchExists && action.singleCommit ? `git diff origin/${action.branch}` : `git status --porcelain`; core_1.info(`Checking if there are files to commit…`); const hasFilesToCommit = action.isTest & constants_1.TestFlag.HAS_CHANGED_FILES || (yield execute_1.execute(checkGitStatus, `${action.workspace}/${temporaryDeploymentDirectory}`, true // This output is always silenced due to the large output it creates. )); if ((!action.singleCommit && !hasFilesToCommit) || // Ignores the case where single commit is true with a target folder to prevent incorrect early exiting. (action.singleCommit && !action.targetFolder && !hasFilesToCommit)) { return constants_1.Status.SKIPPED; } // Commits to GitHub. yield execute_1.execute(`git add --all .`, `${action.workspace}/${temporaryDeploymentDirectory}`, action.silent); yield execute_1.execute(`git checkout -b ${temporaryDeploymentBranch}`, `${action.workspace}/${temporaryDeploymentDirectory}`, action.silent); yield execute_1.execute(`git commit -m "${commitMessage}" --quiet --no-verify`, `${action.workspace}/${temporaryDeploymentDirectory}`, action.silent); if (!action.dryRun) { yield execute_1.execute(`git push --force ${action.repositoryPath} ${temporaryDeploymentBranch}:${action.branch}`, `${action.workspace}/${temporaryDeploymentDirectory}`, action.silent); } core_1.info(`Changes committed to the ${action.branch} branch… 📦`); return constants_1.Status.SUCCESS; } catch (error) { throw new Error(`The deploy step encountered an error: ${util_1.suppressSensitiveInformation(error.message, action)} ❌`); } finally { // Cleans up temporary files/folders and restores the git state. core_1.info('Running post deployment cleanup jobs… 🗑️'); yield execute_1.execute(`git checkout -B ${temporaryDeploymentBranch}`, `${action.workspace}/${temporaryDeploymentDirectory}`, action.silent); yield execute_1.execute(`git worktree remove ${temporaryDeploymentDirectory} --force`, action.workspace, action.silent); yield io_1.rmRF(temporaryDeploymentDirectory); } }); } exports.deploy = deploy;