diff --git a/actions/graybox/promote-worker.js b/actions/graybox/promote-worker.js index 15ddaab..548e288 100644 --- a/actions/graybox/promote-worker.js +++ b/actions/graybox/promote-worker.js @@ -21,10 +21,12 @@ const { } = require('../utils'); const appConfig = require('../appConfig'); const { getConfig } = require('../config'); -const { getAuthorizedRequestOption, fetchWithRetry, updateExcelTable } = require('../sharepoint'); +const { + getAuthorizedRequestOption, fetchWithRetry, updateExcelTable, + getFileData, getFileUsingDownloadUrl, saveFileSimple +} = require('../sharepoint'); const helixUtils = require('../helixUtils'); const updateDocument = require('../docxUpdater'); -const { saveFile, promoteCopy } = require('../sharepoint'); const logger = getAioLogger(); const MAX_CHILDREN = 1000; @@ -75,8 +77,9 @@ async function main(params) { const promotedPreviewStatuses = []; let promotedFailedPreviews = []; - + let responsePayload = ''; if (helixUtils.canBulkPreview(true)) { + logger.info('Bulk Previewing Graybox files'); const paths = []; batchArray.forEach((batch) => { batch.forEach((gbFile) => paths.push(handleExtension(gbFile.filePath))); @@ -121,8 +124,11 @@ async function main(params) { const promotedExcelValues = [['Promoted Files Preview completed', toUTCStr(new Date()), sFailedPromotedPreviews]]; // Update Promoted Preview Status await updateExcelTable(projectExcelPath, 'PROMOTE_STATUS', promotedExcelValues); + responsePayload = 'Graybox Promote Worker action completed.'; + } else { + responsePayload = 'Bulk Preview not enabled for Graybox Content Tree'; } - const responsePayload = 'Graybox Promote Worker action completed.'; + logger.info(responsePayload); return exitAction({ body: responsePayload, }); @@ -163,11 +169,12 @@ async function promoteFiles(previewStatuses, experienceName, helixAdminApiKey) { if (docx) { // Save file Destination full path with file name and extension const destinationFilePath = `${stat.path.substring(0, stat.path.lastIndexOf('/') + 1).replace('/'.concat(experienceName), '')}${stat.fileName}`; + const saveStatus = await saveFileSimple(docx, destinationFilePath, sp); - const saveStatus = await saveFile(docx, destinationFilePath, sp); - - if (saveStatus && saveStatus.success) { + if (saveStatus?.success) { promotes.push(destinationFilePath); + } else if (saveStatus?.errorMsg?.includes('File is locked')) { + failedPromotes.push(`${destinationFilePath} (locked file)`); } else { failedPromotes.push(destinationFilePath); } @@ -177,13 +184,18 @@ async function promoteFiles(previewStatuses, experienceName, helixAdminApiKey) { } else { const copySourceFilePath = `${stat.path.substring(0, stat.path.lastIndexOf('/') + 1)}${stat.fileName}`; // Copy Source full path with file name and extension const copyDestinationFolder = `${stat.path.substring(0, stat.path.lastIndexOf('/')).replace('/'.concat(experienceName), '')}`; // Copy Destination folder path, no file name + const destFilePath = `${copyDestinationFolder}/${stat.fileName}`; - const promoteCopyFileStatus = await promoteCopy(copySourceFilePath, copyDestinationFolder, stat.fileName, sp); + const { fileDownloadUrl } = await getFileData(copySourceFilePath, true); + const file = await getFileUsingDownloadUrl(fileDownloadUrl); + const saveStatus = await saveFileSimple(file, destFilePath, sp); - if (promoteCopyFileStatus) { - promotes.push(`${copyDestinationFolder}/${stat.fileName}`); + if (saveStatus?.success) { + promotes.push(destFilePath); + } else if (saveStatus?.errorMsg?.includes('File is locked')) { + failedPromotes.push(`${destFilePath} (locked file)`); } else { - failedPromotes.push(`${copyDestinationFolder}/${stat.fileName}`); + failedPromotes.push(destFilePath); } } } diff --git a/actions/sharepoint.js b/actions/sharepoint.js index 985702c..d510932 100644 --- a/actions/sharepoint.js +++ b/actions/sharepoint.js @@ -434,62 +434,35 @@ async function saveFile(file, dest, spConfig, isGraybox) { return { success: false, path: dest }; } -/** - * Promote Copy - * Copies the Graaybox files back to the main content tree. - * Creates intermediate folders if needed. -* @param {*} srcPath Graybox Source Path - * @param {*} destinationFolder Promote Destination Folder - * @param {*} fileName FileName to be promoted - * @param {*} sp sharepoint config - * @returns promote status true/false for the file - */ -async function promoteCopy(srcPath, destinationFolder, fileName, sp) { - const { baseURI } = sp.api.file.copy; - const rootFolder = baseURI.split('/').pop(); - await createFolder(destinationFolder, sp); - const payload = { ...sp.api.file.copy.payload, parentReference: { path: `${rootFolder}${destinationFolder}` } }; - - const options = await getAuthorizedRequestOption({ - method: sp.api.file.copy.method, - body: JSON.stringify(payload), - }); - - // copy source is the Graybox directory for promote - const copyStatusInfo = await fetchWithRetry(`${sp.api.file.copy.gbBaseURI}${srcPath}:/copy?@microsoft.graph.conflictBehavior=replace`, options); - const statusUrl = copyStatusInfo.headers.get('Location'); +async function saveFileSimple(file, dest, spConfig, isGraybox) { + const logger = getAioLogger(); - let copySuccess = false; - let copyStatusJson = {}; - while (statusUrl && !copySuccess && copyStatusJson.status !== 'failed') { - // eslint-disable-next-line no-await-in-loop - const status = await fetchWithRetry(statusUrl); - if (status.ok) { - // eslint-disable-next-line no-await-in-loop - copyStatusJson = await status.json(); - copySuccess = copyStatusJson.status === 'completed'; + try { + const folder = getFolderFromPath(dest); + const filename = getFileNameFromPath(dest); + logger.info(`Saving file ${filename} to ${folder}`); + await createFolder(folder, spConfig); + let sp; + if (spConfig) { + sp = spConfig; + } else { + sp = await getConfig().sp; } - } - // If copy failed because it is Locked, try to copy the locked file to a new file, - // then promote copy again, then delete the renamed locked file copy - if (!copySuccess) { - // await releaseUploadSession(sp, uploadFileStatus.sessionUrl); - const lockedFileNewName = getLockedFileNewName(fileName); - // const baseURI = isGraybox ? sp.api.file.get.gbBaseURI : sp.api.file.get.baseURI; - const spFileUrl = `${baseURI}${destinationFolder}/${fileName}`; - await renameFile(spFileUrl, lockedFileNewName); - const folder = getFolderFromPath(`${destinationFolder}/${fileName}`); - const newLockedFilePath = `${folder}/${lockedFileNewName}`; - const copyFileStatus = await copyFile(newLockedFilePath, folder, fileName, false, true, sp); - if (copyFileStatus) { - copySuccess = await promoteCopy(srcPath, destinationFolder, fileName, sp); - if (copySuccess) { - await deleteFile(sp, `${baseURI}${newLockedFilePath}`); - } + const uploadFileStatus = await createSessionAndUploadFile(sp, file, dest, filename, isGraybox); + if (uploadFileStatus.locked) { + logger.info(`Locked file detected: ${dest}`); + return { success: false, path: dest, errorMsg: 'File is locked' }; + } + const uploadedFileJson = uploadFileStatus.uploadedFile; + if (uploadedFileJson) { + return { success: true, uploadedFileJson, path: dest }; } + } catch (error) { + logger.info(`Error while saving file: ${dest} ::: ${error.message}`); + return { success: false, path: dest, errorMsg: error.message }; } - return copySuccess; + return { success: false, path: dest }; } async function getExcelTable(excelPath, tableName) { @@ -581,12 +554,13 @@ module.exports = { executeGQL, getDriveRoot, getExcelTable, + getFileData, getFilesData, getFile, getFileUsingDownloadUrl, copyFile, saveFile, - promoteCopy, + saveFileSimple, createFolder, updateExcelTable, fetchWithRetry,