Skip to content

Commit

Permalink
Merge pull request #144 from deecewan/async-dangerfile
Browse files Browse the repository at this point in the history
[WIP] initial implementation to handle async
  • Loading branch information
orta committed Feb 23, 2017
2 parents f264352 + 9e7515a commit 3c9fa6c
Show file tree
Hide file tree
Showing 9 changed files with 150 additions and 5 deletions.
9 changes: 9 additions & 0 deletions source/dsl/DangerResults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { MarkdownString } from "../dsl/Aliases"
* do not add functions, only data to this interface.
*/
export interface DangerResults {

/**
* Failed messages
* @type {Violation[]}
Expand All @@ -31,3 +32,11 @@ export interface DangerResults {
*/
markdowns: Array<MarkdownString>
}

export interface DangerRuntimeContainer extends DangerResults {
/**
* Asynchronous functions to be run after parsing
* @type {Function[]}
*/
scheduled: Array<Function>
}
18 changes: 14 additions & 4 deletions source/runner/Dangerfile.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import { DangerResults } from "../dsl/DangerResults"
import { DangerRuntimeContainer } from "../dsl/DangerResults"
import { DangerDSLType } from "../dsl/DangerDSL"
import { MarkdownString } from "../dsl/Aliases"

export interface DangerContext {
/**
* Contains asynchronous code to be run after the application has booted.
*
* @param {Function} asyncFunction the function to run asynchronously
*/
schedule(asyncFunction: (p: Promise<any>) => void): void

/**
* Fails a build, outputting a specific reason for failing
*
Expand Down Expand Up @@ -45,7 +52,7 @@ export interface DangerContext {
*
* @type {DangerDSLType}
*/
results: DangerResults
results: DangerRuntimeContainer
}

/** Creates a Danger context, this provides all of the global functions
Expand All @@ -55,19 +62,22 @@ export interface DangerContext {
* @returns {DangerContext} a DangerContext-like API
*/
export function contextForDanger(dsl: DangerDSLType): DangerContext {
const results: DangerResults = {
const results: DangerRuntimeContainer = {
fails: [],
warnings: [],
messages: [],
markdowns: []
markdowns: [],
scheduled: []
}

const schedule = (fn: Function) => results.scheduled.push(fn)
const fail = (message: MarkdownString) => results.fails.push({ message })
const warn = (message: MarkdownString) => results.warnings.push({ message })
const message = (message: MarkdownString) => results.messages.push({ message })
const markdown = (message: MarkdownString) => results.markdowns.push(message)

return {
schedule,
fail,
warn,
message,
Expand Down
18 changes: 17 additions & 1 deletion source/runner/DangerfileRunner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,23 @@ export async function runDangerfileEnvironment(filename: Path, environment: Dang
runtime.requireModule(filename)
})

return environment.context.results
const results = environment.context.results
await Promise.all(results.scheduled.map(fnOrPromise => {
if (fnOrPromise instanceof Promise) {
return fnOrPromise
}
if (fnOrPromise.length === 1) {
// callback-based function
return new Promise(res => fnOrPromise(res))
}
return fnOrPromise()
}))
return {
fails: results.fails,
warnings: results.warnings,
messages: results.messages,
markdowns: results.markdowns,
}
}

/**
Expand Down
45 changes: 45 additions & 0 deletions source/runner/_tests/DangerRunner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,51 @@ describe("with fixtures", () => {
const runtime = await createDangerfileRuntimeEnvironment(context)
await runDangerfileEnvironment(resolve(fixtures, "__DangerfileImportRelative.js"), runtime)
})

it("handles scheduled (async) code", async () => {
const context = await setupDangerfileContext()
const runtime = await createDangerfileRuntimeEnvironment(context)
const results = await runDangerfileEnvironment(resolve(fixtures, "__DangerfileScheduled.js"), runtime)
expect(results).toEqual({
fails: [],
messages: [],
markdowns: [],
warnings: [{ message: "Asynchronous Warning" }],
})
})

it("handles multiple scheduled statements and all message types", async () => {
const context = await setupDangerfileContext()
const runtime = await createDangerfileRuntimeEnvironment(context)
const results = await runDangerfileEnvironment(resolve(fixtures, "__DangerfileMultiScheduled.js"), runtime)
expect(results).toEqual({
fails: [{ message: "Asynchronous Failure" }],
messages: [{ message: "Asynchronous Message" }],
markdowns: ["Asynchronous Markdown"],
warnings: [{ message: "Asynchronous Warning" }],
})
})

it("can execute async/await scheduled functions", async () => {
// this test takes *forever* because of babel-polyfill being required
const context = await setupDangerfileContext()
const runtime = await createDangerfileRuntimeEnvironment(context)
const results = await runDangerfileEnvironment(resolve(fixtures, "__DangerfileAsync.js"), runtime)
expect(results.warnings).toEqual([{
message: "Async Function"
}, {
message: "After Async Function"
}])
})

it("can schedule callback-based promised", async () => {
const context = await setupDangerfileContext()
const runtime = await createDangerfileRuntimeEnvironment(context)
const results = await runDangerfileEnvironment(resolve(fixtures, "__DangerfileCallback.js"), runtime)
expect(results.warnings).toEqual([{
message: "Scheduled a callback",
}])
})
})

describe("cleaning Dangerfiles", () => {
Expand Down
7 changes: 7 additions & 0 deletions source/runner/_tests/fixtures/ExampleDangerResults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,10 @@ export const summaryResults: DangerResults = {
messages: [{ message: "message" }],
markdowns: ["markdown"],
}

export const asyncResults: DangerResults = {
fails: [],
warnings: [],
messages: [],
markdowns: [],
}
15 changes: 15 additions & 0 deletions source/runner/_tests/fixtures/__DangerfileAsync.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*eslint-disable */

import 'babel-polyfill';

const asyncAction = () => new Promise(res => {
setTimeout(() => {
warn('Async Function');
res();
}, 50);
});

schedule(async () => {
await asyncAction();
warn('After Async Function');
});
8 changes: 8 additions & 0 deletions source/runner/_tests/fixtures/__DangerfileCallback.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*eslint-disable */

schedule(done => {
setTimeout(() => {
warn('Scheduled a callback');
done();
});
});
27 changes: 27 additions & 0 deletions source/runner/_tests/fixtures/__DangerfileMultiScheduled.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*eslint-disable */

schedule(new Promise((res) => {
setTimeout(() => {
fail('Asynchronous Failure');
res();
}, 100);
}));

schedule(new Promise((res) => {
warn('Asynchronous Warning');
res();
}));

schedule(new Promise((res) => {
setTimeout(() => {
message('Asynchronous Message');
res();
}, 10);
}));

schedule(new Promise((res) => {
setTimeout(() => {
markdown('Asynchronous Markdown');
res();
}, 50);
}));
8 changes: 8 additions & 0 deletions source/runner/_tests/fixtures/__DangerfileScheduled.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*eslint-disable */

schedule(new Promise((res) => {
setTimeout(() => {
warn('Asynchronous Warning');
res();
}, 10);
}));

0 comments on commit 3c9fa6c

Please sign in to comment.