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
8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@
[![Total Downloads](https://poser.pugx.org/thecodingmachine/washingmachine/downloads)](https://packagist.org/packages/thecodingmachine/washingmachine)
[![Latest Unstable Version](https://poser.pugx.org/thecodingmachine/washingmachine/v/unstable)](https://packagist.org/packages/thecodingmachine/washingmachine)
[![License](https://poser.pugx.org/thecodingmachine/washingmachine/license)](https://packagist.org/packages/thecodingmachine/washingmachine)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/thecodingmachine/washingmachine/badges/quality-score.png?b=1.0)](https://scrutinizer-ci.com/g/thecodingmachine/washingmachine/?branch=1.0)
[![Build Status](https://travis-ci.org/thecodingmachine/washingmachine.svg?branch=1.0)](https://travis-ci.org/thecodingmachine/washingmachine)
[![Coverage Status](https://coveralls.io/repos/thecodingmachine/washingmachine/badge.svg?branch=1.0&service=github)](https://coveralls.io/github/thecodingmachine/washingmachine?branch=1.0)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/thecodingmachine/washingmachine/badges/quality-score.png?b=1.2)](https://scrutinizer-ci.com/g/thecodingmachine/washingmachine/?branch=1.2)
[![Build Status](https://travis-ci.org/thecodingmachine/washingmachine.svg?branch=1.2)](https://travis-ci.org/thecodingmachine/washingmachine)
[![Coverage Status](https://coveralls.io/repos/thecodingmachine/washingmachine/badge.svg?branch=1.2&service=github)](https://coveralls.io/github/thecodingmachine/washingmachine?branch=1.2)


# Washing machine

**Work in progress**

The *washing machine* is a tool that helps you writing cleaner code by integrating PHPUnit with Gitlab CI.

As a result, when you perform a merge request in Gitlab, the washing machine will add meaningful information about your code quality.
Expand Down
40 changes: 29 additions & 11 deletions src/Commands/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,12 @@ public function getGitlabUrl() : string
{
$gitlabUrl = $this->input->getOption('gitlab-url');
if ($gitlabUrl === null) {
$ciProjectUrl = getenv('CI_BUILD_REPO');
$ciProjectUrl = getenv('CI_REPOSITORY_URL');
if ($ciProjectUrl === false) {
throw new \RuntimeException('Could not find the Gitlab URL in the "CI_BUILD_REPO" environment variable (usually set by Gitlab CI). Either set this environment variable or pass the URL via the --gitlab-url command line option.');
$ciProjectUrl = getenv('CI_BUILD_REPO');
if ($ciProjectUrl === false) {
throw new \RuntimeException('Could not find the Gitlab URL in the "CI_REPOSITORY_URL" (Gitlab 9+) or "CI_BUILD_REPO" (Gitlab 8.x) environment variable (usually set by Gitlab CI). Either set this environment variable or pass the URL via the --gitlab-url command line option.');
}
}
$parsed_url = parse_url($ciProjectUrl);
$scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
Expand Down Expand Up @@ -79,25 +82,33 @@ public function getGitlabProjectName() : string
return $projectName;
}

public function getGitlabBuildRef() : string
public function getCommitSha() : string
{
$buildRef = $this->input->getOption('gitlab-build-ref');
if ($buildRef === null) {
$buildRef = getenv('CI_BUILD_REF');
if ($buildRef === false) {
throw new \RuntimeException('Could not find the Gitlab build reference in the "CI_BUILD_REF" environment variable (usually set by Gitlab CI). Either set this environment variable or pass the build reference via the --gitlab-build-ref command line option.');
$commitSha = $this->input->getOption('commit-sha');

if ($commitSha === null) {
$commitSha = getenv('CI_COMMIT_SHA');
if ($commitSha === false) {
$commitSha = getenv('CI_BUILD_REF');
if ($commitSha === false) {
throw new \RuntimeException('Could not find the Gitlab build reference in the "CI_COMMIT_SHA" (Gitlab 9+) or "CI_BUILD_REF" (Gitlab 8.x) environment variable (usually set by Gitlab CI). Either set this environment variable or pass the build reference via the --commit-sha command line option.');
}
}
}
return $buildRef;

return $commitSha;
}

public function getGitlabBuildId() : int
{
$buildId = $this->input->getOption('gitlab-build-id');
$buildId = $this->input->getOption('gitlab-job-id');
if ($buildId === null) {
$buildId = getenv('CI_BUILD_ID');
if ($buildId === false) {
throw new \RuntimeException('Could not find the Gitlab build id in the "CI_BUILD_ID" environment variable (usually set by Gitlab CI). Either set this environment variable or pass the build id via the --gitlab-build-id command line option.');
$buildId = getenv('CI_JOB_ID');
if ($buildId === false) {
throw new \RuntimeException('Could not find the Gitlab build id in the "CI_JOB_ID" (Gitlab 9+) or "CI_BUILD_ID" (Gitlab 8.x) environment variable (usually set by Gitlab CI). Either set this environment variable or pass the build id via the --gitlab-job-id command line option.');
}
}
}
return $buildId;
Expand All @@ -109,11 +120,18 @@ public function getGitlabBuildId() : int
*/
public function getCurrentBranchName() : string
{
// Gitlab 8.x
$branchName = getenv('CI_BUILD_REF_NAME');
if ($branchName !== false) {
return $branchName;
}

// Gitlab 9+
$branchName = getenv('CI_COMMIT_REF_NAME');
if ($branchName !== false) {
return $branchName;
}

$repo = new GitRepository(getcwd());
return $repo->getCurrentBranchName();
}
Expand Down
22 changes: 11 additions & 11 deletions src/Commands/RunCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ protected function configure()
InputOption::VALUE_REQUIRED,
'The Gitlab project name (in the form "group/name"). If not specified, it is deduced from the CI_PROJECT_DIR environment variable.',
null)
->addOption('gitlab-build-ref',
->addOption('commit-sha',
'r',
InputOption::VALUE_REQUIRED,
'The Gitlab CI build reference. If not specified, it is deduced from the CI_BUILD_REF environment variable.',
'The commit SHA. If not specified, it is deduced from the CI_COMMIT_SHA environment variable.',
null)
->addOption('gitlab-build-id',
->addOption('gitlab-job-id',
'b',
InputOption::VALUE_REQUIRED,
'The Gitlab CI build id. If not specified, it is deduced from the CI_BUILD_ID environment variable.',
Expand Down Expand Up @@ -132,7 +132,7 @@ protected function execute(InputInterface $input, OutputInterface $output)

$projectName = $config->getGitlabProjectName();

$buildRef = $config->getGitlabBuildRef();
$commitSha = $config->getCommitSha();

$currentBranchName = $config->getCurrentBranchName();

Expand All @@ -143,7 +143,7 @@ protected function execute(InputInterface $input, OutputInterface $output)

$sendCommentService = new SendCommentService($client, $diffService);

// From CI_BUILD_REF, we can get the commit ( -> project -> build -> commit )
// From CI_COMMIT_SHA, we can get the commit ( -> project -> build -> commit )
// From the merge_requests API, we can get the list of commits for a single merge request
// Hence, we can find the merge_request matching a build!

Expand All @@ -152,11 +152,11 @@ protected function execute(InputInterface $input, OutputInterface $output)
$inMergeRequest = false;

try {
$mergeRequest = $buildService->findMergeRequestByBuildRef($projectName, $buildRef);
$mergeRequest = $buildService->findMergeRequestByCommitSha($projectName, $commitSha);

$repo = new GitRepository(getcwd());
$targetCommit = $repo->getLatestCommitForBranch('origin/'.$mergeRequest['target_branch']);
$lastCommonCommit = $repo->getMergeBase($targetCommit, $buildRef);
$lastCommonCommit = $repo->getMergeBase($targetCommit, $commitSha);


list($previousCodeCoverageProvider, $previousMethodsProvider) = $this->getMeasuresFromCommit($buildService, $mergeRequest['target_project_id'], $lastCommonCommit, $cloverFilePath, $crap4JFilePath);
Expand All @@ -169,7 +169,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$output->writeln('Could not find clover file for code coverage analysis.');
}
if ($methodsProvider !== null) {
$message->addDifferencesHtml($methodsProvider, $previousMethodsProvider, $diffService, $buildRef, $gitlabUrl, $projectName);
$message->addDifferencesHtml($methodsProvider, $previousMethodsProvider, $diffService, $commitSha, $gitlabUrl, $projectName);
} else {
$output->writeln('Could not find clover file nor crap4j file for CRAP score analysis.');
}
Expand All @@ -188,7 +188,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$targetProjectId = $mergeRequest['target_project_id'] ?? $projectName;
list($lastCommitCoverage, $lastCommitMethodsProvider) = $this->getMeasuresFromBranch($buildService, $targetProjectId, $currentBranchName, $cloverFilePath, $crap4JFilePath);

$sendCommentService->sendDifferencesCommentsInCommit($methodsProvider, $lastCommitMethodsProvider, $projectName, $buildRef, $gitlabUrl);
$sendCommentService->sendDifferencesCommentsInCommit($methodsProvider, $lastCommitMethodsProvider, $projectName, $commitSha, $gitlabUrl);


if ($config->isOpenIssue() && !$inMergeRequest) {
Expand All @@ -201,7 +201,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
}

if ($methodsProvider !== null) {
$message->addDifferencesHtml($methodsProvider, $lastCommitMethodsProvider, $diffService, $buildRef, $gitlabUrl, $projectName);
$message->addDifferencesHtml($methodsProvider, $lastCommitMethodsProvider, $diffService, $commitSha, $gitlabUrl, $projectName);
} else {
$output->writeln('Could not find clover file nor crap4j file for CRAP score analysis.');
}
Expand All @@ -214,7 +214,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
'description' => (string) $message
];

$userId = $this->getCommiterId($client, $project, $buildRef);
$userId = $this->getCommiterId($client, $project, $commitSha);
if ($userId !== null) {
$options['assignee_id'] = $userId;
}
Expand Down
8 changes: 4 additions & 4 deletions src/Gitlab/BuildService.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ public function getCommitId(string $projectName, string $buildRef) : string

/**
* @param string $projectName
* @param string $buildRef
* @param string $commitSha
* @return array The merge request object
* @throws MergeRequestNotFoundException
*/
public function findMergeRequestByBuildRef(string $projectName, string $buildRef) : array
public function findMergeRequestByCommitSha(string $projectName, string $commitSha) : array
{
// Find in the last 50 merge requests (since our build was triggered recently, it should definitely be there)
$mergeRequests = $this->client->merge_requests->all($projectName, 1, 50, 'updated_at', 'desc');
Expand All @@ -48,12 +48,12 @@ public function findMergeRequestByBuildRef(string $projectName, string $buildRef
// Let's only return this PR if the returned commit is the FIRST one (otherwise, the commit ID is on an outdated version of the PR)

// Note: strangely, the "id" column of the commit is the build ref and not the commit id... weird!
if ($commits[0]['id'] === $buildRef) {
if ($commits[0]['id'] === $commitSha) {
return $mergeRequest;
}
}

throw new MergeRequestNotFoundException('Could not find a PR (in the 50 last PRs) whose last commit/buildRef ID is '.$buildRef);
throw new MergeRequestNotFoundException('Could not find a PR (in the 50 last PRs) whose last commit/buildRef ID is '.$commitSha);
}

public function getLatestCommitIdFromBranch(string $projectName, string $branchName) : string
Expand Down
40 changes: 32 additions & 8 deletions tests/Commands/ConfigTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ private function getInputDefinition()
InputOption::VALUE_REQUIRED,
'The Gitlab project name (in the form "group/name"). If not specified, it is deduced from the CI_PROJECT_DIR environment variable.',
null),
new InputOption('gitlab-build-ref',
new InputOption('commit-sha',
'r',
InputOption::VALUE_REQUIRED,
'The Gitlab CI build reference. If not specified, it is deduced from the CI_BUILD_REF environment variable.',
'The commit SHA. If not specified, it is deduced from the CI_COMMIT_SHA environment variable.',
null),
new InputOption('gitlab-build-id',
new InputOption('gitlab-job-id',
'b',
InputOption::VALUE_REQUIRED,
'The Gitlab CI build id. If not specified, it is deduced from the CI_BUILD_ID environment variable.',
Expand Down Expand Up @@ -155,25 +155,37 @@ public function testGitlabBuildRefFromEnv()
putenv('CI_BUILD_REF=DEADBEEFDEADBEEF');
$input = new ArrayInput([], $this->getInputDefinition());
$config = new Config($input);
$this->assertSame('DEADBEEFDEADBEEF', $config->getGitlabBuildRef());
$this->assertSame('DEADBEEFDEADBEEF', $config->getCommitSha());
}

public function testGitlab9BuildRefFromEnv()
{
putenv('CI_BUILD_REF');
putenv('CI_COMMIT_SHA=DEADBEEFDEADBEEF');
$input = new ArrayInput([], $this->getInputDefinition());
$config = new Config($input);
$this->assertSame('DEADBEEFDEADBEEF', $config->getCommitSha());
}

public function testGitlabBuildRefFromParam()
{
$input = new ArrayInput(array('--gitlab-build-ref' => 'DEADBEEFDEADBEEF2'), $this->getInputDefinition());
putenv('CI_BUILD_REF');
putenv('CI_COMMIT_SHA');
$input = new ArrayInput(array('--commit-sha' => 'DEADBEEFDEADBEEF2'), $this->getInputDefinition());

$config = new Config($input);
$this->assertSame('DEADBEEFDEADBEEF2', $config->getGitlabBuildRef());
$this->assertSame('DEADBEEFDEADBEEF2', $config->getCommitSha());
}

public function testNoGitlabBuildRef()
{
putenv('CI_BUILD_REF');
putenv('CI_COMMIT_SHA');
$input = new ArrayInput([], $this->getInputDefinition());

$config = new Config($input);
$this->expectException(\RuntimeException::class);
$config->getGitlabBuildRef();
$config->getCommitSha();
}

public function testGitlabBuildIdFromEnv()
Expand All @@ -184,9 +196,21 @@ public function testGitlabBuildIdFromEnv()
$this->assertSame(42, $config->getGitlabBuildId());
}

public function testGitlabJobIdFromEnv()
{
putenv('CI_BUILD_ID');
putenv('CI_JOB_ID=42');
$input = new ArrayInput([], $this->getInputDefinition());
$config = new Config($input);
$this->assertSame(42, $config->getGitlabBuildId());
}

public function testGitlabBuildIdFromParam()
{
$input = new ArrayInput(array('--gitlab-build-id' => '42'), $this->getInputDefinition());
putenv('CI_BUILD_ID');
putenv('CI_JOB_ID');

$input = new ArrayInput(array('--gitlab-job-id' => '42'), $this->getInputDefinition());

$config = new Config($input);
$this->assertSame(42, $config->getGitlabBuildId());
Expand Down