Skip to content

Reviewable Setup

Jamie Snape edited this page Jun 17, 2021 · 5 revisions

Enabling/Disabling

Simply login to Reviewable/Repositories, find this repository and turn the slider on/off as desired.

Completion Condition

This is the most recent "review completion condition script" for drake-external-examples, which repository admins can edit here. This page is for backup purposes. Please try to keep it in sync with the service.

// Any time you edit this file, paste the final version into the drake-external-examples wiki for backup:
// https://reviewable.io/repositories#RobotLocomotion%2Fdrake-external-examples%2F65

var reasons = [];  // pieces of the status description
var summary = review.summary;  // shortcut to summary

// Check that all discussions are resolved.
if (summary.numUnresolvedDiscussions) {
  reasons.push(
    summary.numUnresolvedDiscussions +
    ' unresolved discussion' +
    (summary.numUnresolvedDiscussions === 1 ? '' : 's'));
} else {
  reasons.push('all discussions resolved');
}

// Tabulate the emoji approvals.
var approvals = {};

var platformReviewers = {'ericcousineau-tri' : true,
                         'ggould-tri' : true,
                         'jwnimmer-tri' : true, 
                         'sammy-tri' : true,
                         'seancurtis-tri' : true,
                         'sherm1' : true, 
                         'soonho-tri' : true,
                         'russtedrake' : true,
                         };

// Timestamp of the currently latest revision.
var lastRevisionTimestamp =
  _.last(review.revisions).snapshotTimestamp;

_.each(review.sentiments, function(sentiment) {
  var emojis = _.indexBy(sentiment.emojis);
  if (emojis.lgtm_cancel) {
    delete approvals[sentiment.username];
  } else if (emojis.lgtm_strong || emojis.lgtm || emojis.LGTM) {
    approvals[sentiment.username.toLowerCase()] = true;
  }
});

var allAssigneesHaveApproved = true;
var assignees = review.pullRequest.assignees;
for (var i in assignees) {
  var name = assignees[i].username.toLowerCase();
  var lgtm = approvals[name];
  if (!lgtm) {
    allAssigneesHaveApproved = false;
    reasons.push('LGTM missing from assignee ' + name);
  }
}

var platformApprovers = [];

// An :lgtm: goes for the entire PR.
for (var approver in approvals) {
  if (approvals[approver] && platformReviewers[approver]) {
    platformApprovers.push(approver);
  }
}

var platformExemptFiles = []
var platformNonexemptFiles = []

for (var i in review.files) {
  var file = review.files[i];
  var path = file["path"];
  if (path.includes("/dev/")) {
    platformExemptFiles.push(path);
  } else {
    platformNonexemptFiles.push(path);
  }
}

if (platformNonexemptFiles.length == 0) {
  reasons.push("Exempt from platform review")
} else {
  if (platformApprovers.length == 0) {
    reasons.push('platform LGTM missing');
  } else {
    reasons.push('platform LGTM from [' +
                 platformApprovers.join(', ') + ']');
  }
}

var doNotMerge = review.labels.indexOf('status: do not merge') >= 0;
if (doNotMerge) {
  reasons.push('labeled "do not merge"');
}

var curateNeeded = review.labels.indexOf('status: curate commits before merging') >= 0;
var multipleCommits = review.pullRequest.numCommits > 1;
var requireCuration = curateNeeded && multipleCommits;
if (requireCuration) {
  reasons.push('commit history needs curation');
}

var isMoratorium = false;
if (isMoratorium) {
  reasons.push('moratorium on merges is in effect');
}

return {
  completed: (!isMoratorium &&
              !summary.numUnresolvedDiscussions &&
              (platformApprovers.length > 0 ||
               platformNonexemptFiles.length == 0) &&
              allAssigneesHaveApproved &&
              !doNotMerge &&
              !requireCuration),
  description: reasons.join(', '),
  debug: {'approvals': approvals,
          'platformExemptFiles': platformExemptFiles,
          'platformNonexemptFiles': platformNonexemptFiles}
};
Clone this wiki locally