{"action":"created","comment":{"url":"https://api.github.com/repos/mockito/shipkit/pulls/comments/150291169","pull_request_review_id":75817769,"id":150291169,"diff_hunk":"@@ -15,43 +16,57 @@\n     //For reference, see the \".travis.yml\" of Mockito project\n     private final static String SKIP_RELEASE_ENV = \"SKIP_RELEASE\";\n     private final static String SKIP_RELEASE_KEYWORD = \"[ci skip-release]\";\n+    private static final String FORCE_RELEASE_KEYWORD = \"[ci force-release]\";\n \n     public boolean releaseNeeded(ReleaseNeededTask task) {\n-        return releaseNeeded(task, new EnvVariables());\n+        Pair<Boolean, String> pair = releaseNeeded(task, new EnvVariables());\n+\n+        boolean releaseNeeded = pair.getLeft();\n+        String message = pair.getRight();\n+\n+        if (!releaseNeeded && task.isExplosive()) {\n+            throw new GradleException(message);\n+        } else {\n+            LOG.lifecycle(message);\n+        }\n+        return releaseNeeded;\n     }\n \n-    public boolean releaseNeeded(ReleaseNeededTask task, EnvVariables envVariables) {\n+    Pair<Boolean, String> releaseNeeded(ReleaseNeededTask task, EnvVariables envVariables) {\n         boolean skipEnvVariable = envVariables.getNonEmptyEnv(SKIP_RELEASE_ENV) != null;\n         LOG.lifecycle(\"  Environment variable {} present: {}\", SKIP_RELEASE_ENV, skipEnvVariable);\n \n         boolean commitMessageEmpty = task.getCommitMessage() == null || task.getCommitMessage().trim().isEmpty();\n         boolean skippedByCommitMessage = !commitMessageEmpty && task.getCommitMessage().contains(SKIP_RELEASE_KEYWORD);\n-        LOG.lifecycle(\"  Commit message to inspect for keyword '{}': {}\",\n-                SKIP_RELEASE_KEYWORD,\n-                commitMessageEmpty ? \"<unknown commit message>\" : \"\\n\" + task.getCommitMessage());\n+        boolean forcedByCommitMessage = !commitMessageEmpty && task.getCommitMessage().contains(FORCE_RELEASE_KEYWORD);\n+        LOG.lifecycle(\"  Commit message to inspect for keywords '{}' and '{}': {}\",\n+            SKIP_RELEASE_KEYWORD, FORCE_RELEASE_KEYWORD,\n+            commitMessageEmpty ? \"<unknown commit message>\" : \"\\n\" + task.getCommitMessage());\n \n         boolean releasableBranch = task.getBranch() != null && task.getBranch().matches(task.getReleasableBranchRegex());\n         LOG.lifecycle(\"  Current branch '{}' matches '{}': {}\", task.getBranch(), task.getReleasableBranchRegex(), releasableBranch);\n \n-        ComparisonResults results = new ComparisonResults(task.getComparisonResults());\n-        boolean publicationsIdentical = results.areResultsIdentical();\n-        LOG.lifecycle(results.getDescription());\n+        if (releasableBranch) {\n+            if (skippedByCommitMessage) {\n+                return Pair.of(false, \" Skipping release due to skip release keyword in commit message.\");\n+            } else if (skipEnvVariable) {\n+                return Pair.of(false, \" Skipping release due to skip release env variable.\");\n+            } else if (task.isPullRequest()) {\n+                return Pair.of(false, \" Skipping release due to is PR.\");\n+            } else if (forcedByCommitMessage) {\n+                return Pair.of(true, \" Releasing due to force release keyword in commit message.\");\n+            } else {\n+                ComparisonResults results = new ComparisonResults(task.getComparisonResults());\n+                boolean publicationsIdentical = results.areResultsIdentical();\n+                LOG.lifecycle(results.getDescription());\n \n-        boolean releaseNotNeeded = publicationsIdentical || skipEnvVariable || skippedByCommitMessage || task.isPullRequest() || !releasableBranch;\n-\n-        String message = \"  Release is needed: \" + !releaseNotNeeded +","path":"subprojects/shipkit/src/main/groovy/org/shipkit/internal/gradle/release/tasks/ReleaseNeeded.java","position":66,"original_position":66,"commit_id":"eaa913523581907fc3b6f63d230f48eaf3b507a4","original_commit_id":"eaa913523581907fc3b6f63d230f48eaf3b507a4","user":{"login":"mockitoguy","id":24743,"avatar_url":"https://avatars2.githubusercontent.com/u/24743?v=4","gravatar_id":"","url":"https://api.github.com/users/mockitoguy","html_url":"https://github.com/mockitoguy","followers_url":"https://api.github.com/users/mockitoguy/followers","following_url":"https://api.github.com/users/mockitoguy/following{/other_user}","gists_url":"https://api.github.com/users/mockitoguy/gists{/gist_id}","starred_url":"https://api.github.com/users/mockitoguy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mockitoguy/subscriptions","organizations_url":"https://api.github.com/users/mockitoguy/orgs","repos_url":"https://api.github.com/users/mockitoguy/repos","events_url":"https://api.github.com/users/mockitoguy/events{/privacy}","received_events_url":"https://api.github.com/users/mockitoguy/received_events","type":"User","site_admin":false},"body":"This message is useful for debugging and I don't think we want to get rid of it. See ticket #209 for how we can improve this message.","created_at":"2017-11-10T17:13:59Z","updated_at":"2017-11-10T17:17:43Z","html_url":"https://github.com/mockito/shipkit/pull/565#discussion_r150291169","pull_request_url":"https://api.github.com/repos/mockito/shipkit/pulls/565","author_association":"OWNER","_links":{"self":{"href":"https://api.github.com/repos/mockito/shipkit/pulls/comments/150291169"},"html":{"href":"https://github.com/mockito/shipkit/pull/565#discussion_r150291169"},"pull_request":{"href":"https://api.github.com/repos/mockito/shipkit/pulls/565"}}},"pull_request":{"url":"https://api.github.com/repos/mockito/shipkit/pulls/565","id":151509443,"html_url":"https://github.com/mockito/shipkit/pull/565","diff_url":"https://github.com/mockito/shipkit/pull/565.diff","patch_url":"https://github.com/mockito/shipkit/pull/565.patch","issue_url":"https://api.github.com/repos/mockito/shipkit/issues/565","number":565,"state":"open","locked":false,"title":"Introduce [ci force-release] commit message keyword","user":{"login":"epeee","id":9488377,"avatar_url":"https://avatars0.githubusercontent.com/u/9488377?v=4","gravatar_id":"","url":"https://api.github.com/users/epeee","html_url":"https://github.com/epeee","followers_url":"https://api.github.com/users/epeee/followers","following_url":"https://api.github.com/users/epeee/following{/other_user}","gists_url":"https://api.github.com/users/epeee/gists{/gist_id}","starred_url":"https://api.github.com/users/epeee/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/epeee/subscriptions","organizations_url":"https://api.github.com/users/epeee/orgs","repos_url":"https://api.github.com/users/epeee/repos","events_url":"https://api.github.com/users/epeee/events{/privacy}","received_events_url":"https://api.github.com/users/epeee/received_events","type":"User","site_admin":false},"body":"fixes #353 ","created_at":"2017-11-08T22:10:36Z","updated_at":"2017-11-10T17:17:43Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a4d57790d5cfea6746d03e414f79819c4e1969fe","assignee":null,"assignees":[],"requested_reviewers":[],"milestone":null,"commits_url":"https://api.github.com/repos/mockito/shipkit/pulls/565/commits","review_comments_url":"https://api.github.com/repos/mockito/shipkit/pulls/565/comments","review_comment_url":"https://api.github.com/repos/mockito/shipkit/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mockito/shipkit/issues/565/comments","statuses_url":"https://api.github.com/repos/mockito/shipkit/statuses/eaa913523581907fc3b6f63d230f48eaf3b507a4","head":{"label":"mockito:ep2","ref":"ep2","sha":"eaa913523581907fc3b6f63d230f48eaf3b507a4","user":{"login":"mockito","id":2054056,"avatar_url":"https://avatars0.githubusercontent.com/u/2054056?v=4","gravatar_id":"","url":"https://api.github.com/users/mockito","html_url":"https://github.com/mockito","followers_url":"https://api.github.com/users/mockito/followers","following_url":"https://api.github.com/users/mockito/following{/other_user}","gists_url":"https://api.github.com/users/mockito/gists{/gist_id}","starred_url":"https://api.github.com/users/mockito/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mockito/subscriptions","organizations_url":"https://api.github.com/users/mockito/orgs","repos_url":"https://api.github.com/users/mockito/repos","events_url":"https://api.github.com/users/mockito/events{/privacy}","received_events_url":"https://api.github.com/users/mockito/received_events","type":"Organization","site_admin":false},"repo":{"id":73235879,"name":"shipkit","full_name":"mockito/shipkit","owner":{"login":"mockito","id":2054056,"avatar_url":"https://avatars0.githubusercontent.com/u/2054056?v=4","gravatar_id":"","url":"https://api.github.com/users/mockito","html_url":"https://github.com/mockito","followers_url":"https://api.github.com/users/mockito/followers","following_url":"https://api.github.com/users/mockito/following{/other_user}","gists_url":"https://api.github.com/users/mockito/gists{/gist_id}","starred_url":"https://api.github.com/users/mockito/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mockito/subscriptions","organizations_url":"https://api.github.com/users/mockito/orgs","repos_url":"https://api.github.com/users/mockito/repos","events_url":"https://api.github.com/users/mockito/events{/privacy}","received_events_url":"https://api.github.com/users/mockito/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mockito/shipkit","description":"Toolkit for shipping it used by Mockito library","fork":false,"url":"https://api.github.com/repos/mockito/shipkit","forks_url":"https://api.github.com/repos/mockito/shipkit/forks","keys_url":"https://api.github.com/repos/mockito/shipkit/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mockito/shipkit/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mockito/shipkit/teams","hooks_url":"https://api.github.com/repos/mockito/shipkit/hooks","issue_events_url":"https://api.github.com/repos/mockito/shipkit/issues/events{/number}","events_url":"https://api.github.com/repos/mockito/shipkit/events","assignees_url":"https://api.github.com/repos/mockito/shipkit/assignees{/user}","branches_url":"https://api.github.com/repos/mockito/shipkit/branches{/branch}","tags_url":"https://api.github.com/repos/mockito/shipkit/tags","blobs_url":"https://api.github.com/repos/mockito/shipkit/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mockito/shipkit/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mockito/shipkit/git/refs{/sha}","trees_url":"https://api.github.com/repos/mockito/shipkit/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mockito/shipkit/statuses/{sha}","languages_url":"https://api.github.com/repos/mockito/shipkit/languages","stargazers_url":"https://api.github.com/repos/mockito/shipkit/stargazers","contributors_url":"https://api.github.com/repos/mockito/shipkit/contributors","subscribers_url":"https://api.github.com/repos/mockito/shipkit/subscribers","subscription_url":"https://api.github.com/repos/mockito/shipkit/subscription","commits_url":"https://api.github.com/repos/mockito/shipkit/commits{/sha}","git_commits_url":"https://api.github.com/repos/mockito/shipkit/git/commits{/sha}","comments_url":"https://api.github.com/repos/mockito/shipkit/comments{/number}","issue_comment_url":"https://api.github.com/repos/mockito/shipkit/issues/comments{/number}","contents_url":"https://api.github.com/repos/mockito/shipkit/contents/{+path}","compare_url":"https://api.github.com/repos/mockito/shipkit/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mockito/shipkit/merges","archive_url":"https://api.github.com/repos/mockito/shipkit/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mockito/shipkit/downloads","issues_url":"https://api.github.com/repos/mockito/shipkit/issues{/number}","pulls_url":"https://api.github.com/repos/mockito/shipkit/pulls{/number}","milestones_url":"https://api.github.com/repos/mockito/shipkit/milestones{/number}","notifications_url":"https://api.github.com/repos/mockito/shipkit/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mockito/shipkit/labels{/name}","releases_url":"https://api.github.com/repos/mockito/shipkit/releases{/id}","deployments_url":"https://api.github.com/repos/mockito/shipkit/deployments","created_at":"2016-11-08T23:22:05Z","updated_at":"2017-11-10T11:12:21Z","pushed_at":"2017-11-09T05:19:00Z","git_url":"git://github.com/mockito/shipkit.git","ssh_url":"git@github.com:mockito/shipkit.git","clone_url":"https://github.com/mockito/shipkit.git","svn_url":"https://github.com/mockito/shipkit","homepage":"http://shipkit.org","size":2800,"stargazers_count":53,"watchers_count":53,"language":"Java","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":14,"mirror_url":null,"archived":false,"open_issues_count":51,"forks":14,"open_issues":51,"watchers":53,"default_branch":"master"}},"base":{"label":"mockito:master","ref":"master","sha":"5ceed9cf42e5d918c388629f768996fb5c5686e4","user":{"login":"mockito","id":2054056,"avatar_url":"https://avatars0.githubusercontent.com/u/2054056?v=4","gravatar_id":"","url":"https://api.github.com/users/mockito","html_url":"https://github.com/mockito","followers_url":"https://api.github.com/users/mockito/followers","following_url":"https://api.github.com/users/mockito/following{/other_user}","gists_url":"https://api.github.com/users/mockito/gists{/gist_id}","starred_url":"https://api.github.com/users/mockito/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mockito/subscriptions","organizations_url":"https://api.github.com/users/mockito/orgs","repos_url":"https://api.github.com/users/mockito/repos","events_url":"https://api.github.com/users/mockito/events{/privacy}","received_events_url":"https://api.github.com/users/mockito/received_events","type":"Organization","site_admin":false},"repo":{"id":73235879,"name":"shipkit","full_name":"mockito/shipkit","owner":{"login":"mockito","id":2054056,"avatar_url":"https://avatars0.githubusercontent.com/u/2054056?v=4","gravatar_id":"","url":"https://api.github.com/users/mockito","html_url":"https://github.com/mockito","followers_url":"https://api.github.com/users/mockito/followers","following_url":"https://api.github.com/users/mockito/following{/other_user}","gists_url":"https://api.github.com/users/mockito/gists{/gist_id}","starred_url":"https://api.github.com/users/mockito/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mockito/subscriptions","organizations_url":"https://api.github.com/users/mockito/orgs","repos_url":"https://api.github.com/users/mockito/repos","events_url":"https://api.github.com/users/mockito/events{/privacy}","received_events_url":"https://api.github.com/users/mockito/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mockito/shipkit","description":"Toolkit for shipping it used by Mockito library","fork":false,"url":"https://api.github.com/repos/mockito/shipkit","forks_url":"https://api.github.com/repos/mockito/shipkit/forks","keys_url":"https://api.github.com/repos/mockito/shipkit/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mockito/shipkit/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mockito/shipkit/teams","hooks_url":"https://api.github.com/repos/mockito/shipkit/hooks","issue_events_url":"https://api.github.com/repos/mockito/shipkit/issues/events{/number}","events_url":"https://api.github.com/repos/mockito/shipkit/events","assignees_url":"https://api.github.com/repos/mockito/shipkit/assignees{/user}","branches_url":"https://api.github.com/repos/mockito/shipkit/branches{/branch}","tags_url":"https://api.github.com/repos/mockito/shipkit/tags","blobs_url":"https://api.github.com/repos/mockito/shipkit/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mockito/shipkit/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mockito/shipkit/git/refs{/sha}","trees_url":"https://api.github.com/repos/mockito/shipkit/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mockito/shipkit/statuses/{sha}","languages_url":"https://api.github.com/repos/mockito/shipkit/languages","stargazers_url":"https://api.github.com/repos/mockito/shipkit/stargazers","contributors_url":"https://api.github.com/repos/mockito/shipkit/contributors","subscribers_url":"https://api.github.com/repos/mockito/shipkit/subscribers","subscription_url":"https://api.github.com/repos/mockito/shipkit/subscription","commits_url":"https://api.github.com/repos/mockito/shipkit/commits{/sha}","git_commits_url":"https://api.github.com/repos/mockito/shipkit/git/commits{/sha}","comments_url":"https://api.github.com/repos/mockito/shipkit/comments{/number}","issue_comment_url":"https://api.github.com/repos/mockito/shipkit/issues/comments{/number}","contents_url":"https://api.github.com/repos/mockito/shipkit/contents/{+path}","compare_url":"https://api.github.com/repos/mockito/shipkit/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mockito/shipkit/merges","archive_url":"https://api.github.com/repos/mockito/shipkit/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mockito/shipkit/downloads","issues_url":"https://api.github.com/repos/mockito/shipkit/issues{/number}","pulls_url":"https://api.github.com/repos/mockito/shipkit/pulls{/number}","milestones_url":"https://api.github.com/repos/mockito/shipkit/milestones{/number}","notifications_url":"https://api.github.com/repos/mockito/shipkit/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mockito/shipkit/labels{/name}","releases_url":"https://api.github.com/repos/mockito/shipkit/releases{/id}","deployments_url":"https://api.github.com/repos/mockito/shipkit/deployments","created_at":"2016-11-08T23:22:05Z","updated_at":"2017-11-10T11:12:21Z","pushed_at":"2017-11-09T05:19:00Z","git_url":"git://github.com/mockito/shipkit.git","ssh_url":"git@github.com:mockito/shipkit.git","clone_url":"https://github.com/mockito/shipkit.git","svn_url":"https://github.com/mockito/shipkit","homepage":"http://shipkit.org","size":2800,"stargazers_count":53,"watchers_count":53,"language":"Java","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":14,"mirror_url":null,"archived":false,"open_issues_count":51,"forks":14,"open_issues":51,"watchers":53,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mockito/shipkit/pulls/565"},"html":{"href":"https://github.com/mockito/shipkit/pull/565"},"issue":{"href":"https://api.github.com/repos/mockito/shipkit/issues/565"},"comments":{"href":"https://api.github.com/repos/mockito/shipkit/issues/565/comments"},"review_comments":{"href":"https://api.github.com/repos/mockito/shipkit/pulls/565/comments"},"review_comment":{"href":"https://api.github.com/repos/mockito/shipkit/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mockito/shipkit/pulls/565/commits"},"statuses":{"href":"https://api.github.com/repos/mockito/shipkit/statuses/eaa913523581907fc3b6f63d230f48eaf3b507a4"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"mockitoguy"}}