feat(workflow): add deploy preview links (#2028)

This commit is contained in:
Shawn Erquhart
2019-02-08 12:26:59 -05:00
committed by GitHub
parent f0553c720a
commit 15d221d4a4
24 changed files with 861 additions and 42 deletions

View File

@ -280,6 +280,15 @@ export default class API {
});
}
/**
* Retrieve statuses for a given SHA. Unrelated to the editorial workflow
* concept of entry "status". Useful for things like deploy preview links.
*/
async getStatuses(sha) {
const resp = await this.request(`${this.repoURL}/commits/${sha}/status`);
return resp.statuses;
}
composeFileTree(files) {
let filename;
let part;

View File

@ -6,6 +6,34 @@ import API from './API';
const MAX_CONCURRENT_DOWNLOADS = 10;
/**
* Keywords for inferring a status that will provide a deploy preview URL.
*/
const PREVIEW_CONTEXT_KEYWORDS = ['deploy'];
/**
* Check a given status context string to determine if it provides a link to a
* deploy preview. Checks for an exact match against `previewContext` if given,
* otherwise checks for inclusion of a value from `PREVIEW_CONTEXT_KEYWORDS`.
*/
function isPreviewContext(context, previewContext) {
if (previewContext) {
return context === previewContext;
}
return PREVIEW_CONTEXT_KEYWORDS.some(keyword => context.includes(keyword));
}
/**
* Retrieve a deploy preview URL from an array of statuses. By default, a
* matching status is inferred via `isPreviewContext`.
*/
function getPreviewStatus(statuses, config) {
const previewContext = config.getIn(['backend', 'preview_context']);
return statuses.find(({ context }) => {
return isPreviewContext(context, previewContext);
});
}
export default class GitHub {
constructor(config, options = {}) {
this.config = config;
@ -222,6 +250,28 @@ export default class GitHub {
});
}
/**
* Uses GitHub's Statuses API to retrieve statuses, infers which is for a
* deploy preview via `getPreviewStatus`. Returns the url provided by the
* status, as well as the status state, which should be one of 'success',
* 'pending', and 'failure'.
*/
async getDeployPreview(collection, slug) {
const data = await this.api.retrieveMetadata(slug);
if (!data) {
return null;
}
const statuses = await this.api.getStatuses(data.pr.head);
const deployStatus = getPreviewStatus(statuses, this.config);
if (deployStatus) {
const { target_url, state } = deployStatus;
return { url: target_url, status: state };
}
}
updateUnpublishedEntryStatus(collection, slug, newStatus) {
return this.api.updateUnpublishedEntryStatus(collection, slug, newStatus);
}