diff --git a/scripts/azpipelines/upload-to-storage.js b/scripts/azpipelines/upload-to-storage.js index 9b727cd205..b514aa9d1c 100644 --- a/scripts/azpipelines/upload-to-storage.js +++ b/scripts/azpipelines/upload-to-storage.js @@ -4,9 +4,13 @@ const fs = require("fs"); const path = require("path"); const azureStorage = require("azure-storage"); const { getManifest, getContainerName } = require("./utils"); +const crypto = require("crypto"); const storageAccountName = process.env.AZURE_STORAGE_ACCOUNT; const storageAccountKey = process.argv[2]; +const attemptNumber = Number(process.env.Release_AttemptNumber); + +console.log(`This is the ${attemptNumber} try to release`); if (!storageAccountKey) { console.error("No storage account key passed"); @@ -16,9 +20,24 @@ if (!storageAccountKey) { console.log("Uploading to storage account:", storageAccountName); const blobService = azureStorage.createBlobService(storageAccountName, storageAccountKey); -async function uploadToBlob(container, filename, blobName, override = false) { - console.log(`Uploading ${filename} ====> Container=${container}, Blobname=${blobName}`); +function computeFileMd5(filename) { + const data = fs.readFileSync(filename); + return crypto.createHash("md5").update(data).digest("base64"); +} +async function getBlob(container, blobName) { + return new Promise((resolve, reject) => { + blobService.getBlobProperties(container, blobName, (error, result, response) => { + if (error) { + return reject(error); + } + + resolve(result); + }); + }); +} + +async function createBlobFromLocalFile(container, filename, blobName, override = false) { const options = {}; if (!override) { options.accessConditions = azureStorage.AccessCondition.generateIfNotExistsCondition(); @@ -27,8 +46,10 @@ async function uploadToBlob(container, filename, blobName, override = false) { return new Promise((resolve, reject) => { blobService.createBlockBlobFromLocalFile(container, blobName, filename, options, (error, result, response) => { + if (error) { reject(error); + return; } console.log("Uploaded", result, response); @@ -37,6 +58,26 @@ async function uploadToBlob(container, filename, blobName, override = false) { }); } +async function uploadToBlob(container, filename, blobName, override = false) { + console.log(`Uploading ${filename} ====> Container=${container}, Blobname=${blobName}`); + try { + return await createBlobFromLocalFile(container, filename, blobName, override); + } catch (error) { + if (error.code === "BlobAlreadyExists") { + const blob = await getBlob(container, blobName); + const md5 = computeFileMd5(filename); + const blobMd5 = blob.contentSettings && blob.contentSettings.contentMD5; + if (md5 === blobMd5) { + console.log(`Already uploaded ${filename} skipping(Md5 hash matched)`); + } else { + throw new Error(`Error blob already exists but doesn't match the local file. ${md5} != ${blobMd5}`); + } + } else { + throw error; + } + } +} + async function uploadFiles(os) { const manifest = getManifest(os); console.log(`Uploading ${manifest.files.length} files for os: ${os}`);