Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@ os:
- linux
language: d
d:
- dmd-nightly
- dmd-beta
- dmd
- ldc-beta
- ldc

matrix:
allow_failures:
- d: ldc
include:
- d: dmd-2.070.2 # the deployment compiler
env: COVERAGE=true
Expand Down
2 changes: 1 addition & 1 deletion dub.sdl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ copyright "Copyright © 2015, Martin Nowak"
authors "Martin Nowak"
dependency "vibe-d" version="~>0.7.30"
configuration "default" {
versions "VibeDefaultMain"
versions "VibeCustomMain"
targetType "executable"
}
configuration "unittest" {
Expand Down
81 changes: 42 additions & 39 deletions source/dlangbot/app.d
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ public import dlangbot.bugzilla : bugzillaURL;
public import dlangbot.github : githubAPIURL, githubAuth, hookSecret;
public import dlangbot.trello : trelloAPIURL, trelloAuth, trelloSecret;

string cronDailySecret;

import std.datetime : Clock, days, Duration, minutes, seconds, SysTime;

import vibe.core.args;
import vibe.core.core;
import vibe.core.log;
import vibe.data.json;
import vibe.http.client : HTTPClient;
Expand All @@ -29,32 +29,6 @@ Duration prInactivityDur = 90.days; // PRs with no activity within X days will g

enum trelloHookURL = "https://dlang-bot.herokuapp.com/trello_hook";

version(unittest){} else
shared static this()
{
import std.process : environment;
import vibe.core.args : readOption;

auto settings = new HTTPServerSettings;
settings.port = 8080;
readOption("port|p", &settings.port, "Sets the port used for serving.");
startServer(settings);

githubAuth = "token "~environment["GH_TOKEN"];
trelloSecret = environment["TRELLO_SECRET"];
trelloAuth = "key="~environment["TRELLO_KEY"]~"&token="~environment["TRELLO_TOKEN"];
hookSecret = environment["GH_HOOK_SECRET"];
cronDailySecret = environment["CRON_DAILY_SECRET"];

// workaround for stupid openssl.conf on Heroku
if (environment.get("DYNO") !is null)
{
HTTPClient.setTLSSetupCallback((ctx) {
ctx.useTrustedCertificateFile("/etc/ssl/certs/ca-certificates.crt");
});
}
}

void startServer(HTTPServerSettings settings)
{
import vibe.core.core : vibeVersionString;
Expand All @@ -71,7 +45,6 @@ void startServer(HTTPServerSettings settings)
.post("/github_hook", &githubHook)
.match(HTTPMethod.HEAD, "/trello_hook", (req, res) => res.writeVoidBody)
.post("/trello_hook", &trelloHook)
.get("/cron_daily", &cronDaily)
;

HTTPClient.setUserAgentString("dlang-bot vibe.d/"~vibeVersionString);
Expand Down Expand Up @@ -152,19 +125,13 @@ void githubHook(HTTPServerRequest req, HTTPServerResponse res)

//==============================================================================

void cronDaily(HTTPServerRequest req, HTTPServerResponse res)
void cronDaily()
{
enforceBadRequest(req.query.length > 0, "No repo slugs provided");
enforceHTTP(req.query.get("secret") == cronDailySecret,
HTTPStatus.unauthorized, "Invalid or no secret provided");

foreach (ref slug; req.query.getAll("repo"))
foreach (repo; ["dlang/phobos"])
{
logInfo("running cron.daily for: %s", slug);
runTaskHelper(&searchForInactivePrs, slug, prInactivityDur);
logInfo("running cron.daily for: %s", repo);
searchForInactivePrs(repo, prInactivityDur);
}

return res.writeBody("OK");
}

//==============================================================================
Expand Down Expand Up @@ -213,3 +180,39 @@ void handlePR(string action, PullRequest* _pr)
if (runTrello)
updateTrelloCard(action, pr.htmlURL, refs, descs);
}

//==============================================================================

version (unittest) {}
else void main(string[] args)
{
import std.process : environment;
import vibe.core.args : readOption;

githubAuth = "token "~environment["GH_TOKEN"];
trelloSecret = environment["TRELLO_SECRET"];
trelloAuth = "key="~environment["TRELLO_KEY"]~"&token="~environment["TRELLO_TOKEN"];
hookSecret = environment["GH_HOOK_SECRET"];

// workaround for stupid openssl.conf on Heroku
if (environment.get("DYNO") !is null)
{
HTTPClient.setTLSSetupCallback((ctx) {
ctx.useTrustedCertificateFile("/etc/ssl/certs/ca-certificates.crt");
});
}

bool runDailyCron;
auto settings = new HTTPServerSettings;
settings.port = 8080;
readOption("port|p", &settings.port, "Sets the port used for serving.");
readOption("cron-daily", &runDailyCron, "Run daily cron tasks.");
if (!finalizeCommandLineOptions())
return;
if (runDailyCron)
return cronDaily();

startServer(settings);
lowerPrivileges();
runEventLoop();
}
2 changes: 1 addition & 1 deletion source/dlangbot/github.d
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ struct PullRequest
}
Branch base, head;
enum State { open, closed }
enum MergeableState { clean, dirty, unstable, unknown }
enum MergeableState { clean, dirty, unstable, blocked, unknown }
@byName State state;
uint number;
string title;
Expand Down
3 changes: 2 additions & 1 deletion test/cronjob.d
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,6 @@ unittest
},
);

openUrl("/cron_daily?repo=dlang/phobos&secret=" ~ cronDailySecret, "OK");
import dlangbot.app : cronDaily;
cronDaily();
}
14 changes: 9 additions & 5 deletions test/utils.d
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ shared static this()
githubAuth = "GH_DUMMY_AUTH_TOKEN";
hookSecret = "GH_DUMMY_HOOK_SECRET";
trelloAuth = "key=01234&token=abcde";
cronDailySecret = "dummyCronSecret";

// start our hook server
auto settings = new HTTPServerSettings;
Expand Down Expand Up @@ -124,9 +123,12 @@ auto payloadServer(scope HTTPServerRequest req, scope HTTPServerResponse res)
if (expectation.jsonHandler !is null)
expectation.jsonHandler(payloadJson);

payload = payloadJson.toString;
return res.writeJsonBody(payloadJson);
}
else
{
return res.writeBody(payload);
}
return res.writeBody(payload);
}
}

Expand Down Expand Up @@ -168,18 +170,19 @@ struct APIExpectation
}
}

APIExpectation[] apiExpectations;
__gshared APIExpectation[] apiExpectations;

void setAPIExpectations(Args...)(Args args)
{
import std.functional : toDelegate;
import std.traits : Parameters;
synchronized {
apiExpectations.length = 0;
foreach (i, arg; args)
{
static if (is(Args[i] : string))
{
apiExpectations ~= APIExpectation(arg);
apiExpectations ~= APIExpectation(arg);
}
else
{
Expand All @@ -200,6 +203,7 @@ void setAPIExpectations(Args...)(Args args)
apiExpectations[$ - 1].reqHandler is null, "Either provide a reqHandler or a jsonHandler");
}
}
}
}

void postGitHubHook(string payload, string eventType = "pull_request",
Expand Down