Skip to content

Commit

Permalink
Use public Heroku API
Browse files Browse the repository at this point in the history
  • Loading branch information
mheap committed May 25, 2020
1 parent a9e0137 commit e117acb
Show file tree
Hide file tree
Showing 8 changed files with 6,309 additions and 1,033 deletions.
33 changes: 29 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,31 @@
FROM node:10.14.2-alpine
WORKDIR /app
# Use the latest version of Node.js
#
# You may prefer the full image:
# FROM node
#
# or even an alpine image (a smaller, faster, less-feature-complete image):
# FROM node:alpine
#
# You can specify a version:
# FROM node:10-slim
FROM node:slim

# Labels for GitHub to read your action
LABEL "com.github.actions.name"="Heroku Review Application"
LABEL "com.github.actions.description"="Create a Heroku review app when a PR is raised by someone with write or admin access"
# Here are all of the available icons: https://feathericons.com/
LABEL "com.github.actions.icon"="book-open"
# And all of the available colors: https://developer.github.com/actions/creating-github-actions/creating-a-docker-container/#label
LABEL "com.github.actions.color"="orange"

# Copy the package.json and package-lock.json
COPY package*.json ./
RUN npm install --only=production

# Install dependencies
RUN npm ci

# Copy the rest of your action's code
COPY . .
ENTRYPOINT ["node", "/app/create-review-app.js"]

# Run `node /index.js`
ENTRYPOINT ["node", "/index.js"]
45 changes: 0 additions & 45 deletions README.md

This file was deleted.

15 changes: 7 additions & 8 deletions action.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
name: 'Heroku Review Apps for contributors'
description: 'Create a Heroku review app when a PR is raised by someone with write or admin access'
author: 'Michael Heap'
branding:
icon: 'book-open'
color: 'orange'
name: Heroku Review Application
description: Create a Heroku review app when a PR is raised by someone with write or admin access
runs:
using: 'docker'
image: 'Dockerfile'
using: docker
image: Dockerfile
branding:
icon: book-open
color: orange
105 changes: 0 additions & 105 deletions create-review-app.js

This file was deleted.

109 changes: 109 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
const { Toolkit } = require("actions-toolkit");

const Heroku = require("heroku-client");
const heroku = new Heroku({ token: process.env.HEROKU_API_TOKEN });

// Run your GitHub Action!
Toolkit.run(
async (tools) => {
const pr = tools.context.payload.pull_request;

// Required information
const branch = pr.head.ref;
const version = pr.head.sha;
const fork = pr.head.repo.fork;
const pr_number = pr.number;
const source_url = `${pr.head.repo.html_url}/tarball/${branch}`;

let fork_repo_id;
if (fork) {
fork_repo_id = pr.head.repo.id;
}

tools.log.debug("Deploy Info", {
branch,
version,
fork,
pr_number,
source_url,
});

// Do they have the required permissions?
let requiredCollaboratorPermission = process.env.COLLABORATOR_PERMISSION;
if (requiredCollaboratorPermission) {
requiredCollaboratorPermission = requiredCollaboratorPermission.split(
","
);
} else {
requiredCollaboratorPermission = ["triage", "write", "maintain", "admin"];
}

const reviewAppLabelName =
process.env.REVIEW_APP_LABEL_NAME || "review-app";

const perms = await tools.github.repos.getCollaboratorPermissionLevel({
...tools.context.repo,
username: tools.context.actor,
});

if (!requiredCollaboratorPermission.includes(perms.data.permission)) {
tools.exit.success("User is not a collaborator. Skipping");
}

tools.log.info(`User is a collaborator: ${perms.data.permission}`);

let createReviewApp = false;

let action = tools.context.payload.action;
if (["opened", "synchronize"].indexOf(action) !== -1) {
tools.log.info("PR opened by collaborator");
createReviewApp = true;
await tools.github.issues.addLabels({
...tools.context.repo,
labels: ["review-app"],
issue_number: pr_number,
});
} else if (action === "labeled") {
const labelName = tools.context.payload.label.name;
tools.log.info(`${labelName} label was added by collaborator`);

if (labelName === reviewAppLabelName) {
createReviewApp = true;
} else {
tools.log.debug(`Unexpected label, not creating app: ${labelName}`);
}
}

if (createReviewApp) {
try {
tools.log.pending("Creating review app");
const resp = await heroku.post("/review-apps", {
body: {
branch,
pipeline: process.env.HEROKU_PIPELINE_ID,
source_blob: {
url: source_url,
version,
},
fork_repo_id,
pr_number,
},
});
tools.log.complete("Created review app");
} catch (e) {
// A 409 is a conflict, which means the app already exists
if (e.statusCode !== 409) {
throw e;
}
}
}
},
{
event: [
"pull_request.opened",
"pull_request.synchronize",
"pull_request.labeled",
],
secrets: ["GITHUB_TOKEN", "HEROKU_API_TOKEN", "HEROKU_PIPELINE_ID"],
}
);
23 changes: 23 additions & 0 deletions index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const { Toolkit } = require('actions-toolkit')

describe('Heroku Review Application', () => {
let action, tools

// Mock Toolkit.run to define `action` so we can call it
Toolkit.run = jest.fn((actionFn) => { action = actionFn })
// Load up our entrypoint file
require('.')

beforeEach(() => {
// Create a new Toolkit instance
tools = new Toolkit()
// Mock methods on it!
tools.exit.success = jest.fn()
})

it('exits successfully', () => {
action(tools)
expect(tools.exit.success).toHaveBeenCalled()
expect(tools.exit.success).toHaveBeenCalledWith('We did it!')
})
})
Loading

0 comments on commit e117acb

Please sign in to comment.