index.js
function(buildOutputDirectory) {
    createPercyBuildInvoked = true;

    var token = process.env.PERCY_TOKEN;
    var apiUrl = process.env.PERCY_API; // Optional.

    // Disable if Percy is explicitly disabled or if this is not an 'ember test' run.
    if (process.env.PERCY_ENABLE == '0' || process.env.EMBER_ENV !== 'test') {
      isPercyEnabled = false;
    }

    if (token && isPercyEnabled) {
      console.warn('[percy] Percy is running.');
      percyClient = new PercyClient({
        token: token,
        apiUrl: apiUrl,
        clientInfo: this._clientInfo(),
        environmentInfo: this._environmentInfo(),
      });
    } else {
      isPercyEnabled = false;
      if (!token) {
        console.warn(
          '[percy][WARNING] Percy is disabled, no PERCY_TOKEN environment variable found.')
      }
    }

    if (!isPercyEnabled) { return; }

    var resources = percyClient.gatherBuildResources(buildOutputDirectory, {
      baseUrlPath: percyConfig.baseUrlPath,
      skippedPathRegexes: SKIPPED_ASSETS,
    });

    // Initialize the percy client and a new build.
    percyBuildPromise = percyClient.createBuild({resources: resources});

    // Return a promise and only resolve when all build resources are uploaded, which
    // ensures that the output build dir is still available to be read from before deleted.
    return new Promise(function(resolve) {
      percyBuildPromise.then(
        function(buildResponse) {
          var percyBuildData = buildResponse.body.data;
          console.log('\n[percy] Build created:', percyBuildData.attributes['web-url']);

          // Upload all missing build resources.
          var missingResources = parseMissingResources(buildResponse);
          if (missingResources && missingResources.length > 0) {

            // Note that duplicate resources with the same SHA will get clobbered here into this
            // hash, but that is ok since we only use this to access the content below for upload.
            var hashToResource = {};
            resources.forEach(function(resource) {
              hashToResource[resource.sha] = resource;
            });

            var missingResourcesIndex = 0;
            var promiseGenerator = function() {
              var missingResource = missingResources[missingResourcesIndex];
              missingResourcesIndex++;

              if (missingResource) {
                var resource = hashToResource[missingResource.id];
                var content = fs.readFileSync(resource.localPath);

                // Start the build resource upload and add it to a collection we can block on later
                // because build resources must be fully uploaded before snapshots are finalized.
                var promise = percyClient.uploadResource(percyBuildData.id, content);
                promise.then(function() {
                  console.log('\n[percy] Uploaded new build resource: ' + resource.resourceUrl);
                }, handlePercyFailure);
                buildResourceUploadPromises.push(promise);

                return promise;
              } else {
                // Trigger the pool to end.
                return null;
              }
            }

            // We do this in a promise pool for two reasons: 1) to limit the number of files that
            // are held in memory concurrently, and 2) without a pool, all upload promises are
            // created at the same time and request-promise timeout settings begin immediately,
            // which timeboxes ALL uploads to finish within one timeout period. With a pool, we
            // defer creation of the upload promises, which makes timeouts apply more individually.
            var concurrency = 2;
            var pool = new PromisePool(promiseGenerator, concurrency);

            // Wait for all build resource uploads before we allow the addon build step to complete.
            // If an upload failed, resolve anyway to unblock the building process.
            pool.start().then(resolve, resolve);
          } else {
            // No missing resources.
            resolve();
          }
        },

        function(error) {
          handlePercyFailure(error);

          // If Percy build creation fails, resolve anyway to unblock the building process.
          resolve();
        }
      );
    });
  }
function(buildOutputDirectory) {
    createPercyBuildInvoked = true;

    var token = process.env.PERCY_TOKEN;
    var apiUrl = process.env.PERCY_API; // Optional.

    // Disable if Percy is explicitly disabled or if this is not an 'ember test' run.
    if (process.env.PERCY_ENABLE == '0' || process.env.EMBER_ENV !== 'test') {
      isPercyEnabled = false;
    }

    if (token && isPercyEnabled) {
      console.warn('[percy] Percy is running.');
      percyClient = new PercyClient({
        token: token,
        apiUrl: apiUrl,
        clientInfo: this._clientInfo(),
        environmentInfo: this._environmentInfo(),
      });
    } else {
      isPercyEnabled = false;
      if (!token) {
        console.warn(
          '[percy][WARNING] Percy is disabled, no PERCY_TOKEN environment variable found.')
      }
    }

    if (!isPercyEnabled) { return; }

    var resources = percyClient.gatherBuildResources(buildOutputDirectory, {
      baseUrlPath: percyConfig.baseUrlPath,
      skippedPathRegexes: SKIPPED_ASSETS,
    });

    // Initialize the percy client and a new build.
    percyBuildPromise = percyClient.createBuild({resources: resources});

    // Return a promise and only resolve when all build resources are uploaded, which
    // ensures that the output build dir is still available to be read from before deleted.
    return new Promise(function(resolve) {
      percyBuildPromise.then(
        function(buildResponse) {
          var percyBuildData = buildResponse.body.data;
          console.log('\n[percy] Build created:', percyBuildData.attributes['web-url']);

          // Upload all missing build resources.
          var missingResources = parseMissingResources(buildResponse);
          if (missingResources && missingResources.length > 0) {

            // Note that duplicate resources with the same SHA will get clobbered here into this
            // hash, but that is ok since we only use this to access the content below for upload.
            var hashToResource = {};
            resources.forEach(function(resource) {
              hashToResource[resource.sha] = resource;
            });

            var missingResourcesIndex = 0;
            var promiseGenerator = function() {
              var missingResource = missingResources[missingResourcesIndex];
              missingResourcesIndex++;

              if (missingResource) {
                var resource = hashToResource[missingResource.id];
                var content = fs.readFileSync(resource.localPath);

                // Start the build resource upload and add it to a collection we can block on later
                // because build resources must be fully uploaded before snapshots are finalized.
                var promise = percyClient.uploadResource(percyBuildData.id, content);
                promise.then(function() {
                  console.log('\n[percy] Uploaded new build resource: ' + resource.resourceUrl);
                }, handlePercyFailure);
                buildResourceUploadPromises.push(promise);

                return promise;
              } else {
                // Trigger the pool to end.
                return null;
              }
            }

            // We do this in a promise pool for two reasons: 1) to limit the number of files that
            // are held in memory concurrently, and 2) without a pool, all upload promises are
            // created at the same time and request-promise timeout settings begin immediately,
            // which timeboxes ALL uploads to finish within one timeout period. With a pool, we
            // defer creation of the upload promises, which makes timeouts apply more individually.
            var concurrency = 2;
            var pool = new PromisePool(promiseGenerator, concurrency);

            // Wait for all build resource uploads before we allow the addon build step to complete.
            // If an upload failed, resolve anyway to unblock the building process.
            pool.start().then(resolve, resolve);
          } else {
            // No missing resources.
            resolve();
          }
        },

        function(error) {
          handlePercyFailure(error);

          // If Percy build creation fails, resolve anyway to unblock the building process.
          resolve();
        }
      );
    });
  }
function ( buildOutputDirectory ) { createPercyBuildInvoked = true ; var token = process . env . PERCY_TOKEN ; var apiUrl = process . env . PERCY_API ; // Optional. // Disable if Percy is explicitly disabled or if this is not an 'ember test' run. if ( process . env . PERCY_ENABLE == '0' || process . env . EMBER_ENV !== 'test' ) { isPercyEnabled = false ; } if ( token && isPercyEnabled ) { console . warn ( '[percy] Percy is running.' ) ; percyClient = new PercyClient ( { token : token , apiUrl : apiUrl , clientInfo : this . _clientInfo ( ) , environmentInfo : this . _environmentInfo ( ) , } ) ; } else { isPercyEnabled = false ; if ( ! token ) { console . warn ( '[percy][WARNING] Percy is disabled, no PERCY_TOKEN environment variable found.' ) } } if ( ! isPercyEnabled ) { return ; } var resources = percyClient . gatherBuildResources ( buildOutputDirectory , { baseUrlPath : percyConfig . baseUrlPath , skippedPathRegexes : SKIPPED_ASSETS , } ) ; // Initialize the percy client and a new build. percyBuildPromise = percyClient . createBuild ( { resources : resources } ) ; // Return a promise and only resolve when all build resources are uploaded, which // ensures that the output build dir is still available to be read from before deleted. return new Promise ( function ( resolve ) { percyBuildPromise . then ( function ( buildResponse ) { var percyBuildData = buildResponse . body . data ; console . log ( '\n[percy] Build created:' , percyBuildData . attributes [ 'web-url' ] ) ; // Upload all missing build resources. var missingResources = parseMissingResources ( buildResponse ) ; if ( missingResources && missingResources . length > 0 ) { // Note that duplicate resources with the same SHA will get clobbered here into this // hash, but that is ok since we only use this to access the content below for upload. var hashToResource = { } ; resources . forEach ( function ( resource ) { hashToResource [ resource . sha ] = resource ; } ) ; var missingResourcesIndex = 0 ; var promiseGenerator = function ( ) { var missingResource = missingResources [ missingResourcesIndex ] ; missingResourcesIndex ++ ; if ( missingResource ) { var resource = hashToResource [ missingResource . id ] ; var content = fs . readFileSync ( resource . localPath ) ; // Start the build resource upload and add it to a collection we can block on later // because build resources must be fully uploaded before snapshots are finalized. var promise = percyClient . uploadResource ( percyBuildData . id , content ) ; promise . then ( function ( ) { console . log ( '\n[percy] Uploaded new build resource: ' + resource . resourceUrl ) ; } , handlePercyFailure ) ; buildResourceUploadPromises . push ( promise ) ; return promise ; } else { // Trigger the pool to end. return null ; } } // We do this in a promise pool for two reasons: 1) to limit the number of files that // are held in memory concurrently, and 2) without a pool, all upload promises are // created at the same time and request-promise timeout settings begin immediately, // which timeboxes ALL uploads to finish within one timeout period. With a pool, we // defer creation of the upload promises, which makes timeouts apply more individually. var concurrency = 2 ; var pool = new PromisePool ( promiseGenerator , concurrency ) ; // Wait for all build resource uploads before we allow the addon build step to complete. // If an upload failed, resolve anyway to unblock the building process. pool . start ( ) . then ( resolve , resolve ) ; } else { // No missing resources. resolve ( ) ; } } , function ( error ) { handlePercyFailure ( error ) ; // If Percy build creation fails, resolve anyway to unblock the building process. resolve ( ) ; } ) ; } ) ; }
Create a Percy build and upload missing build resources.
Create a Percy build and upload missing build resources .