docs: 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();
          }
        );
      });
    }