Skip to content

Commit

Permalink
Merge pull request #5 from marczhermo/develop
Browse files Browse the repository at this point in the history
Reference and various fixes
  • Loading branch information
marczhermo authored May 22, 2019
2 parents 670d7fe + e9b19dc commit 730d630
Show file tree
Hide file tree
Showing 9 changed files with 242 additions and 27 deletions.
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,13 @@

Create a deployment with Git SHA
```
./nautpie.phar deploy:naut createDeployment --stack=example --environment=teststack1 --ref=40char-sha --ref_type=sha --bypass_and_start=true
./nautpie.phar deploy:naut createDeployment \
--stack=example \
--environment=teststack1 \
--ref=40char-sha \
--ref_type=sha \
--bypass_and_start=true \
--should_wait=true
```

Calls Git Fetch
Expand All @@ -36,3 +42,8 @@ Last Deployment Details
```
./nautpie.phar deploy:naut lastDeployment --stack=example --environment=teststack1
```

## Reference
- Deploynaut API documentation - https://platform.silverstripe.com/static/api.html
- Blog post (Hayden) using API for deployments - https://www.silverstripe.org/blog/automating-deployments-to-the-silverstripe-platform-with-gitlab/
- Blog post (Jake) using API for deployments - https://www.silverstripe.org/blog/introducing-a-new-approach-to-deployments/
17 changes: 12 additions & 5 deletions src/BitbucketCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ protected function execute(InputInterface $input, OutputInterface $output)
$response = $this->executeAction($action);
} catch (\Exception $e) {
$body = json_decode($e->getMessage(), 1);
if (isset($body['body'])) {
$body = $body['body'];
}

if (is_null($body)) {
$this->warning($e->getMessage());
Expand Down Expand Up @@ -90,7 +93,13 @@ public function doDeployPackage()
'BITBUCKET_BRANCH'
);

$tokenResponse = $this->doCreateAccessToken();
// $tokenResponse = $this->doCreateAccessToken();
// $accessToken = $tokenResponse['body']['access_token'];
$tokenDeploymentInput = new ArrayInput([
'command' => 'ci:bitbucket',
'action' => 'createAccessToken',
]);
$tokenResponse = $this->runCommand('ci:bitbucket', $tokenDeploymentInput);
$accessToken = $tokenResponse['body']['access_token'];

$downloadLink = sprintf(
Expand All @@ -102,9 +111,7 @@ public function doDeployPackage()
$accessToken
);

$command = $this->getApplication()->find('deploy:naut');
$command->resetCurlData();
$createDeploymentInput = new ArrayInput([
$deploymentInput = new ArrayInput([
'command' => 'deploy:naut',
'action' => 'createDeployment',
'--stack' => $stack,
Expand All @@ -117,7 +124,7 @@ public function doDeployPackage()
'--should_wait' => $this->getOption('should_wait'),
]);

return $command->run($createDeploymentInput, $this->output);
return $this->runCommand('deploy:naut', $deploymentInput);
}

public function doCreateTag()
Expand Down
8 changes: 5 additions & 3 deletions src/CurlHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -153,17 +153,19 @@ public function fetchUrl($relativeUrl, $httpMethod = 'GET', $body = null)
$contents = $stream->getContents();
$response['body'] = json_decode($contents, true);

if ($this->isErrorResponse((int) $response['status'])) {
throw new \Exception($contents, (int) $response['status']);
}

return [
'status' => $response['status'],
'reason' => $response['reason'],
'body'=> $response['body'],
];
}

public function isErrorResponse($statusCode)
public function isErrorResponse($statusCode = 0)
{
$statusCode = $statusCode ?: 0;

return $statusCode < 200 || $statusCode > 399;
}

Expand Down
10 changes: 6 additions & 4 deletions src/DeployNautCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ protected function execute(InputInterface $input, OutputInterface $output)

/**
* Creates a deployment on Cloud Platform
* @return string JSON response
* @return array JSON response
*/
public function doCreateDeployment()
{
Expand Down Expand Up @@ -151,7 +151,7 @@ public function doCreateDeployment()

/**
* This is similar on Cloud Platform which executes a git fetch.
* @return string JSON Response
* @return array JSON Response
*/
public function doGitFetch()
{
Expand Down Expand Up @@ -194,12 +194,14 @@ public function doGitFetch()
$isWaiting = false;
}
} while ($isWaiting);

return $response;
}

/**
* Fetches the Cloud Platform of a collection of deployments over the last year.
* Sorted from the latest deployment first
* @return string JSON Response
* @return array JSON Response
*/
public function doGetDeployments()
{
Expand Down Expand Up @@ -252,7 +254,7 @@ function($itemA, $itemB) {
/**
* Get the latest deployment
* Uses doGetDeployments and return the first record
* @return string JSON Response
* @return array JSON Response
*/
public function doLastDeployment()
{
Expand Down
46 changes: 46 additions & 0 deletions src/InputOutputHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,52 @@ public function message($message, $template = 'info')
);
}

/**
* Gets the display returned by the last execution of the command.
*
* @param bool $normalize Whether to normalize end of lines to \n or not
*
* @return string The display
*/
public function getDisplay($normalize = false)
{
$stream = $this->output->getStream();
rewind($stream);

$display = stream_get_contents($stream);

if ($normalize) {
$display = str_replace(PHP_EOL, "\n", $display);
}

$displays = array_filter(explode(PHP_EOL, $display));
$lastDisplay = end($displays);

return $lastDisplay;
}

/**
* Run other commands
* @see BitbucketCommand::doDeployPackage() for sample implementation
* @param string $name A command name or a command alias
* @param ArrayInput $arrayInput
* @return array JSON response string
*/
public function runCommand($name, $arrayInput)
{
$command = $this->getApplication()->find($name);
$command->resetCurlData();
$exitCode = (int) $command->run($arrayInput, $this->output);
$contents = $command->getDisplay();
$response = json_decode($contents, true);

if ($exitCode) {
throw new \Exception($contents, (int) $response['status']);
}

return $response;
}

public function checkRequiredOptions()
{
$args = [];
Expand Down
12 changes: 12 additions & 0 deletions tests/fixtures/createDeploymentError.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"status": 400,
"reason": "Bad Request",
"body": {
"errors": [
{
"status": "400",
"title": "The provided package has a problem: Unable to read files in selected package, or it is empty. Refusing to proceed."
}
]
}
}
40 changes: 40 additions & 0 deletions tests/fixtures/createDeploymentSuccess.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"status": 201,
"reason": "Created",
"body": {
"data": {
"type": "deployments",
"id": "64040",
"attributes": {
"id": 64040,
"date_created_unix": 1553053258,
"date_started_unix": 1553053258,
"date_requested_unix": 0,
"date_approved_unix": 1553053258,
"date_updated_unix": 1553053258,
"title": "[CD:Package] COMMIT_HASH",
"summary": "Branch:develop",
"ref_type": "package",
"ref_name": null,
"rejected_reason": "",
"deployment_type": "code-only",
"deployment_estimate": "2",
"sha": null,
"short_sha": "",
"package_link": "https://api.bitbucket.org/2.0/repositories/repo-owner/repo-slug/downloads/COMMIT_HASH.tar.gz",
"package_id": 10668,
"commit_subject": null,
"commit_message": null,
"approver_id": "",
"approver": null,
"state": "Queued",
"is_current_build": false,
"dirty": false,
"schedule_start_unix": 0,
"schedule_end_unix": 0,
"locked_by": null,
"is_full_deployment": false
}
}
}
}
69 changes: 69 additions & 0 deletions tests/php/BitbucketCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,73 @@ public function testCreateAccessToken()
$this->assertEquals(null, $response['reason']);
$this->assertEquals($expectedReturnedData, $response['body']);
}

public function testDeployPackageSuccess()
{
$tokenCommand = new BitbucketCommand();
$tokenCommand->resetCurlData();
$expectedTokendData = [
'access_token' => 'R2uy6EHAKD7K1q3IG9FHf1B4hq9IprTHiLsT0HnA=',
'scopes' => 'repository',
'expires_in' => 7200,
'refresh_token' => 'Sdyr6UewYGxsmgDH78',
'token_type' => 'bearer',
];
$expectedResponse = [
'status' => 200,
'reason' => null,
'body' => json_encode($expectedTokendData),
];

$tokenHandler = new MockHandler($expectedResponse);
$tokenCommand->setHandler($tokenHandler);
$this->app->add($tokenCommand);

$jsonResponse = json_decode(file_get_contents(dirname(__FILE__) . '/../fixtures/createDeploymentSuccess.json'), 1);
$expectedDeployData = $jsonResponse['body'];
$expectedDeployResponse = [
'status' => $jsonResponse['status'],
'reason' => $jsonResponse['reason'],
'body' => json_encode($expectedDeployData),
];

$deployCommand = new DeployNautCommand();
$deployCommand->resetCurlData();
$deployHandler = new MockHandler($expectedDeployResponse);
$deployCommand->setHandler($deployHandler);
$this->app->add($deployCommand);

$command = $this->command;
$command->resetCurlData();
$handler = new MockHandler([]);
$commandTester = new CommandTester($command);
$exitCode = $commandTester->execute(
[
'command' => $command->getName(),
'action' => 'DeployPackage',
'--commit' => 'COMMIT_HASH_40_REQUIRED_CHARS_1234567890',
'--stack' => 'stack',
'--environment' => 'uat',
]
);

$displays = array_filter(explode(PHP_EOL, $commandTester->getDisplay()));
$this->assertEquals(0, $exitCode, 'Must be Zero for CLI success');

$tokenResponse = json_decode($displays[0], true);
$deployResponse = json_decode($displays[1], true);
$commandResponse = json_decode($displays[2], true);

$this->assertEquals(200, $tokenResponse['status']);
$this->assertEquals(null, $tokenResponse['reason']);
$this->assertEquals($expectedTokendData, $tokenResponse['body']);

$this->assertEquals(201, $deployResponse['status']);
$this->assertEquals('Created', $deployResponse['reason']);
$this->assertEquals($expectedDeployData, $deployResponse['body']);

$this->assertEquals(201, $commandResponse['status']);
$this->assertEquals('Created', $commandResponse['reason']);
$this->assertEquals($expectedDeployData, $commandResponse['body']);
}
}
54 changes: 40 additions & 14 deletions tests/php/DeployNautCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -270,23 +270,15 @@ public function testLastDeployment()
$this->assertEquals(reset($first['data']), $response['body']);
}

public function testCreateDeployment()
public function testCreateDeploymentSuccess()
{
$command = $this->command;
$data = $command->resetCurlData();
$expectedReturnedData = [
'data' => [
'type' => 'deployments',
'id' => '64040',
'attributes' => [
'id' => 640640,
'title' => '[CD:Package] COMMIT_HASH'
]
],
];
$jsonResponse = json_decode(file_get_contents(dirname(__FILE__) . '/../fixtures/createDeploymentSuccess.json'), 1);
$expectedReturnedData = $jsonResponse['body'];
$expectedResponse = [
'status' => 201,
'reason' => 'Created',
'status' => $jsonResponse['status'],
'reason' => $jsonResponse['reason'],
'body' => json_encode($expectedReturnedData),
];

Expand All @@ -305,10 +297,44 @@ public function testCreateDeployment()
);

// the output of the command in the console
$response = json_decode($commandTester->getDisplay(), 1);
$response = json_decode($commandTester->getDisplay(), true);

$this->assertEquals(201, $response['status']);
$this->assertEquals('Created', $response['reason']);
$this->assertEquals($expectedReturnedData, $response['body']);
}

public function testCreateDeploymentGoneBad()
{
$command = $this->command;
$data = $command->resetCurlData();
$jsonResponse = json_decode(file_get_contents(dirname(__FILE__) . '/../fixtures/createDeploymentError.json'), 1);
$expectedReturnedData = $jsonResponse['body'];
$expectedResponse = [
'status' => $jsonResponse['status'],
'reason' => $jsonResponse['reason'],
'body' => json_encode($expectedReturnedData),
];

$handler = new MockHandler($expectedResponse);
$command->setHandler($handler);
$commandTester = new CommandTester($command);
$commandTester->execute(
[
'command' => $command->getName(),
'action' => 'createDeployment',
'--stack' => 'stack',
'--environment' => 'uat',
'--ref_type' => 'branch',
'--ref' => 'develop',
]
);

// the output of the command in the console
$response = json_decode($commandTester->getDisplay(), true);

$this->assertEquals(400, $response['status']);
$this->assertEquals('Bad Request', $response['reason']);
$this->assertEquals($expectedReturnedData, $response['body']);
}
}

0 comments on commit 730d630

Please sign in to comment.