<commit_before>#!/usr/bin/env node

if (!process.env.CI) require('dotenv-safe').load();

const args = require('minimist')(process.argv.slice(2), {
  boolean: [
    'validateRelease',
    'verboseNugget'
  ],
  default: { verboseNugget: false }
});
const fs = require('fs');
const { execSync } = require('child_process');
const got = require('got');
const pkg = require('../../package.json');
const pkgVersion = `v${pkg.version}`;
const path = require('path');
const temp = require('temp').track();
const { URL } = require('url');
const { BlobServiceClient } = require('@azure/storage-blob');
const { Octokit } = require('@octokit/rest');

require('colors');
const pass = '✓'.green;
const fail = '✗'.red;

const { ELECTRON_DIR } = require('../lib/utils');
const getUrlHash = require('./get-url-hash');

const octokit = new Octokit({
  auth: process.env.ELECTRON_GITHUB_TOKEN
});

const targetRepo = pkgVersion.indexOf('nightly') > 0 ? 'nightlies' : 'electron';
let failureCount = 0;

async function getDraftRelease (version, skipValidation) {
  const releaseInfo = await octokit.repos.listReleases({
    owner: 'electron',
    repo: targetRepo
  });

  const versionToCheck = version || pkgVersion;
  const drafts = releaseInfo.data.filter(release => {
    return release.tag_name === versionToCheck && release.draft === true;
  });

  const draft = drafts[0];
  if (!skipValidation) {
    failureCount = 0;
    check(drafts.length === 1, 'one draft exists', true);
    if (versionToCheck.indexOf('beta') > -1) {
      check(draft.prerelease, 'draft is a prerelease');
    }
    check(draft.body.length > 50 && !draft.body.includes('(placeholder)'), 'draft has release notes');
    check((failureCount === 0), 'Draft release looks good to go.', true);
  }
  return draft;
}

async function validateReleaseAssets (release, validatingRelease) {
  const requiredAssets = assetsForVersion(release.tag_name, validatingRelease).sort();
  const extantAssets = release.assets.map(asset => asset.name).sort();
  const downloadUrls = release.assets.map(asset => ({ url: asset.browser_download_url, file: asset.name })).sort((a, b) => a.file.localeCompare(b.file));

  failureCount = 0;
  requiredAssets.forEach(asset => {
    check(extantAssets.includes(asset), asset);
  });
  check((failureCount === 0), 'All required GitHub assets exist for release', true);

  if (!validatingRelease || !release.draft) {
    if (release.draft) {
      await verifyDraftGitHubReleaseAssets(release);
    } else {
      await verifyShasumsForRemoteFiles(downloadUrls)
        .catch(err => {
          console.log(`${fail} error verifyingShasums`, err);
        });
    }
    const s3RemoteFiles = s3RemoteFilesForVersion(release.tag_name);
    await verifyShasumsForRemoteFiles(s3RemoteFiles, true);
    const azRemoteFiles = azRemoteFilesForVersion(release.tag_name);
    await verifyShasumsForRemoteFiles(s3RemoteFiles, true);
  }
}

function check (condition, statement, exitIfFail = false) {
  if (condition) {
    console.log(`${pass} ${statement}`);
  } else {
    failureCount++;
    console.log(`${fail} ${statement}`);
    if (exitIfFail) process.exit(1);
  }
}

function assetsForVersion (version, validatingRelease) {
  const patterns = [
    `chromedriver-${version}-darwin-x64.zip`,
    `chromedriver-${version}-darwin-arm64.zip`,
    `chromedriver-${version}-linux-arm64.zip`,
    `chromedriver-${version}-linux-armv7l.zip`,
    `chromedriver-${version}-linux-x64.zip`,
    `chromedriver-${version}-mas-x64.zip`,<commit_msg>build: actually verify az urls too (#33929)<commit_after>#!/usr/bin/env node

if (!process.env.CI) require('dotenv-safe').load();

const args = require('minimist')(process.argv.slice(2), {
  boolean: [
    'validateRelease',
    'verboseNugget'
  ],
  default: { verboseNugget: false }
});
const fs = require('fs');
const { execSync } = require('child_process');
const got = require('got');
const pkg = require('../../package.json');
const pkgVersion = `v${pkg.version}`;
const path = require('path');
const temp = require('temp').track();
const { URL } = require('url');
const { BlobServiceClient } = require('@azure/storage-blob');
const { Octokit } = require('@octokit/rest');

require('colors');
const pass = '✓'.green;
const fail = '✗'.red;

const { ELECTRON_DIR } = require('../lib/utils');
const getUrlHash = require('./get-url-hash');

const octokit = new Octokit({
  auth: process.env.ELECTRON_GITHUB_TOKEN
});

const targetRepo = pkgVersion.indexOf('nightly') > 0 ? 'nightlies' : 'electron';
let failureCount = 0;

async function getDraftRelease (version, skipValidation) {
  const releaseInfo = await octokit.repos.listReleases({
    owner: 'electron',
    repo: targetRepo
  });

  const versionToCheck = version || pkgVersion;
  const drafts = releaseInfo.data.filter(release => {
    return release.tag_name === versionToCheck && release.draft === true;
  });

  const draft = drafts[0];
  if (!skipValidation) {
    failureCount = 0;
    check(drafts.length === 1, 'one draft exists', true);
    if (versionToCheck.indexOf('beta') > -1) {
      check(draft.prerelease, 'draft is a prerelease');
    }
    check(draft.body.length > 50 && !draft.body.includes('(placeholder)'), 'draft has release notes');
    check((failureCount === 0), 'Draft release looks good to go.', true);
  }
  return draft;
}

async function validateReleaseAssets (release, validatingRelease) {
  const requiredAssets = assetsForVersion(release.tag_name, validatingRelease).sort();
  const extantAssets = release.assets.map(asset => asset.name).sort();
  const downloadUrls = release.assets.map(asset => ({ url: asset.browser_download_url, file: asset.name })).sort((a, b) => a.file.localeCompare(b.file));

  failureCount = 0;
  requiredAssets.forEach(asset => {
    check(extantAssets.includes(asset), asset);
  });
  check((failureCount === 0), 'All required GitHub assets exist for release', true);

  if (!validatingRelease || !release.draft) {
    if (release.draft) {
      await verifyDraftGitHubReleaseAssets(release);
    } else {
      await verifyShasumsForRemoteFiles(downloadUrls)
        .catch(err => {
          console.log(`${fail} error verifyingShasums`, err);
        });
    }
    const s3RemoteFiles = s3RemoteFilesForVersion(release.tag_name);
    await verifyShasumsForRemoteFiles(s3RemoteFiles, true);
    const azRemoteFiles = azRemoteFilesForVersion(release.tag_name);
    await verifyShasumsForRemoteFiles(azRemoteFiles, true);
  }
}

function check (condition, statement, exitIfFail = false) {
  if (condition) {
    console.log(`${pass} ${statement}`);
  } else {
    failureCount++;
    console.log(`${fail} ${statement}`);
    if (exitIfFail) process.exit(1);
  }
}

function assetsForVersion (version, validatingRelease) {
  const patterns = [
    `chromedriver-${version}-darwin-x64.zip`,
    `chromedriver-${version}-darwin-arm64.zip`,
    `chromedriver-${version}-linux-arm64.zip`,
    `chromedriver-${version}-linux-armv7l.zip`,
    `chromedriver-${version}-linux-x64.zip`,
    `chromedriver-${version}-mas-x64.zip`,
{'fraction_non_alphanumeric': 0.1621315192743764, 'fraction_numerical': 0.008503401360544218, 'mean_word_length': 4.391138273491214, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2328284', 'n_tokens_mistral': 2309, 'n_tokens_neox': 2239, 'n_words': 465}