1 module doveralls.doveralls;
2 import doveralls.sourcefiles, doveralls.git, doveralls.request;
3 
4 /**
5  * The tool's entry point.
6  *
7  * Params:
8  *      path =      The path to the root of the repository
9  *      token =     The authorization token for coveralls.io
10  *      service =   Used to differentiate between common services (travis-ci vs travis-pro)
11  *      dump =      Print the coveralls request JSON instead of sending it
12  *
13  * Returns: status code (0 or 1)
14  */
15 int execute(string path, string token, string service, bool dump)
16 {
17     import std.stdio, std.process : env=environment;
18     import std.json: JSONValue, JSONType;
19 
20     JSONValue[string] data;
21     JSONValue[string] ext;
22     if (env.get("TRAVIS"))
23     {
24         data["service_job_id"] = env["TRAVIS_JOB_ID"];
25         data["service_name"] = service.length ? service : "travis-ci"; // could be travis-pro
26         ext["travis_job_id"] = env["TRAVIS_JOB_ID"];
27         ext["travis_pull_request"] = env["TRAVIS_PULL_REQUEST"];
28     }
29     else
30     if (env.get("GITHUB_ACTIONS"))
31     {
32         data["service_name"] = "github";
33         data["repo_token"] = token = env.get("COVERALLS_REPO_TOKEN", token);
34         if (!token.length && !dump)
35         {
36             stderr.writeln("The GitHub token is required when running on GitHub Actions.");
37             stderr.writeln("Either pass ${{ secrets.GITHUB_TOKEN }} as argument or set the COVERALLS_REPO_TOKEN env variable.");
38             return 1;
39         }
40         data["service_number"] = env["GITHUB_RUN_ID"];
41         ext["branch"] = env["GITHUB_REF"];
42         ext["commit_sha"] = env["GITHUB_SHA"];
43     }
44     else if (env.get("CIRCLECI"))
45     {
46         data["service_name"] = "circleci";
47         data["service_number"] = env["CIRCLE_BUILD_NUM"];
48         ext["circleci_build_num"] = env["CIRCLE_BUILD_NUM"];
49         ext["branch"] = env["CIRCLE_BRANCH"];
50         ext["commit_sha"] = env["CIRCLE_SHA1"];
51     }
52     else if (env.get("SEMAPHORE"))
53     {
54         data["service_name"] = "semaphore";
55         data["service_number"] = env["SEMAPHORE_BUILD_NUMBER"];
56     }
57     else if (env.get("JENKINS_URL"))
58     {
59         data["service_name"] = "jenkins";
60         data["service_number"] = env["BUILD_NUMBER"];
61         ext["jenkins_build_num"] = env["BUILD_NUMBER"];
62         ext["jenkins_build_url"] = env["BUILD_URL"];
63         ext["branch"] = env["GIT_BRANCH"];
64         ext["commit_sha"] = env["GIT_COMMIT"];
65     }
66     else if (env.get("CI_NAME"))
67     {
68         data["service_name"] = env["CI_NAME"];
69         data["service_number"] = env["CI_BUILD_NUMBER"];
70         data["service_build_url"] = env["CI_BUILD_URL"];
71         data["service_branch"] = env["CI_BRANCH"];
72         data["service_pull_request"] = env["CI_PULL_REQUEST"];
73     }
74     else
75     {
76         data["service_name"] = "coveralls-ruby";
77         data["repo_token"] = token = env.get("COVERALLS_REPO_TOKEN", token);
78         if (!token.length && !dump)
79         {
80             stderr.writeln("A repo_token is required when running locally.");
81             stderr.writeln("Either pass one as argument or set the COVERALLS_REPO_TOKEN env variable.");
82             return 1;
83         }
84     }
85 
86     import std.datetime : Clock, UTC;
87 
88     if (ext.length) data["environment"] = JSONValue(ext);
89     data["source_files"] = getSourceFiles(path);
90     const git = getGitEntry(path);
91     if (git.type != JSONType.null_)
92         data["git"] = git;
93     data["run_at"] = Clock.currTime(UTC()).toISOExtString();
94 
95     if (!dump)
96         return sendData(JSONValue(data));
97     writeln(JSONValue(data));
98     return 0;
99 }