Skip to content

Commit

Permalink
Added htmlspecialchars() to commit messages as & might break confluen…
Browse files Browse the repository at this point in the history
…ce pushes
  • Loading branch information
alexander.heidrich committed Feb 21, 2020
1 parent 39bd708 commit 1020e6e
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 90 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@
### Installation
Check `Resources/config/services.yaml` for example configuration.

### Usage
```
bin/console confluence:send-release-notes <version-tag>
bin/console confluence:send-release-notes v0.0.2
```

First, this command will get all tags from the repository.
Then it will search for the defined version/tag and the tag, which was set just before.
After this, it will get all commits between these two tags.

If you use the first tag in your repo, it will take all commits from the inital commit to the first tag for changelog-creation.

#### Symfony 4.x Configuration
Make sure to enable the Bundle in `app/config/bundles.php`, e.g.

Expand Down
39 changes: 13 additions & 26 deletions ReleaseNotesBundle/Command/GitChangelog.sh
Original file line number Diff line number Diff line change
@@ -1,32 +1,19 @@
#!/bin/bash

# todo => actual version tag needs to become a variable! ($1)
# @todo use this script as a possibility to get the tag before a specific tag
#
# Author: Alexander.Heidrich
#ACTUAL_VERSION_TAG=$1
#PREVIOUS_VERSION_TAG=
#
#TAG_LIST=($(git tag -l | sort -V))
#length=${#TAG_LIST[@]}
#
#for (( i = 0; i < length; i++ )); do
# if [[ "${TAG_LIST[$i]}" == "${ACTUAL_VERSION_TAG}" ]]; then
# if [[ "$i" -gt "0" ]]; then
# PREVIOUS_VERSION_TAG=${TAG_LIST[$i - 1]} # the tag in the tag list just before the current, actual tag
# else
# PREVIOUS_VERSION_TAG=$(git rev-list --max-parents=0 HEAD) # first commit
# fi
# fi
#done
#
#echo $(git log --pretty="format:%s" "$PREVIOUS_VERSION_TAG".."$ACTUAL_VERSION_TAG")
ACTUAL_VERSION_TAG=$1
PREVIOUS_VERSION_TAG=

#get tag of actual version
ACTUAL_VERSION_TAG=$(git tag | tail -1)
TAG_LIST=($(git tag -l))
length=${#TAG_LIST[@]}

#get tag of the version before actual version
PREVIOUS_VERSION_TAG=$(git tag | tail -3 | head -n 1)
for (( i = 0; i < length; i++ )); do
if [[ "${TAG_LIST[$i]}" == "${ACTUAL_VERSION_TAG}" ]]; then
if [[ "$i" -gt "0" ]]; then
PREVIOUS_VERSION_TAG=${TAG_LIST[$i - 1]} # the tag in the tag list just before the current, actual tag
else
PREVIOUS_VERSION_TAG=$(git rev-list --max-parents=0 HEAD) # first commit
fi
fi
done

#echo $listOfTickets
git log --pretty="format:%s" "$PREVIOUS_VERSION_TAG".."$ACTUAL_VERSION_TAG"
191 changes: 127 additions & 64 deletions ReleaseNotesBundle/Command/ReleaseNotesPublisherCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,29 @@
use Exception;
use GuzzleHttp\Client as HttpClient;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class ReleaseNotesPublisherCommand extends Command
{
public const HTTP_OK = 200;
private const HTTP_OK = 200;
private const INPUT_PARAM_VERSION_TAG = 'version-tag';

/**
* @var string
*/
private $pageTitle = '';

/**
* @var string
*/
private $body = '';

/**
* @var string
*/
private $pageId = '';

/**
* @var HttpClient
Expand All @@ -20,17 +37,27 @@ class ReleaseNotesPublisherCommand extends Command
/**
* @var string
*/
private $pageTitle = '';
private $versionTag;

/**
* @var OutputInterface
*/
private $output;

/**
* @var string
*/
private $body = '';
private $confluenceUser;

/**
* @var string
*/
private $pageId = '';
private $confluencePassword;

/**
* @var string
*/
private $confluenceUrl;

/**
* @param string $confluenceUser
Expand All @@ -45,71 +72,78 @@ public function __construct(
string $pageId
) {
parent::__construct();
$this->client = new HttpClient(
[
'headers' => [
'Content-Type' => 'application/json',
],
'auth' => [
$confluenceUser,
$confluencePassword,
],
'base_uri' => rtrim($confluenceUrl, '/') . '/rest/api/content/',
'timeout' => 2,
]
);
$this->confluenceUser = $confluenceUser;
$this->confluencePassword = $confluencePassword;
$this->confluenceUrl = $confluenceUrl;
$this->pageId = $pageId;
}

/**
* @return HttpClient
*/
private function getClient()
{
if (!$this->client) {
$this->client = new HttpClient(
[
'headers' => [
'Content-Type' => 'application/json',
],
'auth' => [
$this->confluenceUser,
$this->confluencePassword,
],
'base_uri' => rtrim($this->confluenceUrl, '/') . '/rest/api/content/',
'timeout' => 2,
]
);
}

return $this->client;
}

protected function configure(): void
{
$this->setName('confluence:send-release-notes')
->setDescription('Send Version and Changelog of actual Release to Confluence');
$this
->setName('confluence:send-release-notes')
->setDescription(
'Creating changelog information based on the difference between two git tags. Writes it to a confluence page.'
)
->addArgument(self::INPUT_PARAM_VERSION_TAG, InputArgument::REQUIRED, 'The git version-rag');
}

/**
* @param InputInterface $input
* @param OutputInterface $output
*
* @return int
*
* @throws Exception
*/
public function execute(InputInterface $input, OutputInterface $output)
{
$appVersion = getenv('APP_VERSION');
$this->output = $output;
$this->versionTag = $input->getArgument(self::INPUT_PARAM_VERSION_TAG);

$this->retrieveDocumentInformation();

if (stripos($this->body, $appVersion) === false) {
$tickets = $this->extractTickets();
$completeChangelog = $this->extractAndPrepareWholeChangelog();
$this->updateDocumentContent($appVersion, $tickets, $completeChangelog);
if (stripos($this->body, $this->versionTag) === false) {
$this->updateDocumentContent();
$this->preparePayloadAndSendToConfluence();
} else {
echo 'The app version is already part of the changelog.';
$output->writeln('The app version is already part of the changelog.');
}

return 0;
}

/**
* @param string $command
*
* @return array
* @throws Exception
*/
private function extractTickets(): array
private function getCommandOutput(string $command): array
{
$bashPath = dirname(__DIR__) . '/' . basename(__DIR__);
$onlyWebTickets = explode(
PHP_EOL,
shell_exec('/bin/bash ' . $bashPath . '/GitChangelog.sh | grep -Eo \'([A-Z]{3,}-)([0-9]+)\' | uniq')
);
$onlyWebTickets = array_unique(
array_filter(
$onlyWebTickets,
function ($value) {
return stripos($value, 'web-0000') === false && !empty($value);
}
)
);

return $onlyWebTickets;
return explode(PHP_EOL, shell_exec($command));
}

/**
Expand All @@ -118,10 +152,11 @@ function ($value) {
*/
private function extractAndPrepareWholeChangelog(): string
{
$content = '';
$bashPath = dirname(__DIR__) . '/' . basename(__DIR__);
$fileContents = explode(PHP_EOL, shell_exec('/bin/bash ' . $bashPath . '/GitChangelog.sh '));
$command = '/bin/bash ' . $bashPath . '/GitChangelog.sh ' . $this->versionTag;
$fileContents = $this->getCommandOutput($command);

$content = '';
foreach ($fileContents as $commitMessage) {
$content .= '<li>' . htmlspecialchars($commitMessage) . '</li>';
}
Expand All @@ -143,7 +178,7 @@ private function extractAndPrepareWholeChangelog(): string
*/
private function getNextDocumentVersion(): int
{
$response = $this->client->request('GET', $this->pageId);
$response = $this->getClient()->request('GET', $this->pageId);

if ($response->getStatusCode() !== self::HTTP_OK) {
throw new Exception('Could not get response');
Expand All @@ -161,7 +196,7 @@ private function getNextDocumentVersion(): int
*/
private function retrieveDocumentInformation()
{
$response = $this->client->request('GET', $this->pageId . '?expand=body.storage');
$response = $this->getClient()->request('GET', $this->pageId . '?expand=body.storage');
if ($response->getStatusCode() !== self::HTTP_OK) {
throw new Exception('Could not get response');
}
Expand All @@ -173,27 +208,55 @@ private function retrieveDocumentInformation()
}

/**
* @param string $appVersion
* @param array $tickets
* @param string $completeChangelog
* @throws Exception
*/
private function updateDocumentContent(string $appVersion, array $tickets, string $completeChangelog)
private function updateDocumentContent()
{
$headline = '<h2>' . $this->versionTag . ' - ' . date('Y-m-d H:i', time()) . '</h2>';
$ticketList = '<ul>';
foreach (array_unique($tickets) as $ticket) {
if (strtoupper($ticket) !== 'WEB-0000') {
$ticketList .= '
<li>
<ac:structured-macro ac:name="jira" ac:schema-version="1">
<ac:parameter ac:name="server">Jira f&uuml;r DB Connect</ac:parameter>
<ac:parameter ac:name="key">' . $ticket . '</ac:parameter>
</ac:structured-macro>
</li>';
}
$extractedTickets = $this->getTicketIds();
foreach ($extractedTickets as $ticket) {
$ticketList .= '
<li>
<ac:structured-macro ac:name="jira" ac:schema-version="1">
<ac:parameter ac:name="server">Jira f&uuml;r DB Connect</ac:parameter>
<ac:parameter ac:name="key">' . $ticket . '</ac:parameter>
</ac:structured-macro>
</li>';
}
$ticketList .= '</ul>';
$changelog = $this->extractAndPrepareWholeChangelog();

$this->body = '<p><h2>' . $appVersion . '</h2>' . $ticketList . '</p>' . $completeChangelog . $this->body;
$body = '<p>';
$body .= $headline;
$body .= $ticketList;
$body .= '</p>';
$body .= $changelog;
$body .= $this->body;

$this->body = $body;
}

/**
* @return array
* @throws Exception
*/
private function getTicketIds(): array
{
$bashPath = dirname(__DIR__) . '/' . basename(__DIR__);
$command = '/bin/bash ' . $bashPath . '/GitChangelog.sh ' . $this->versionTag . ' | grep -Eo \'([A-Z]{3,}-)([0-9]+)\' | uniq';

$onlyWebTickets = $this->getCommandOutput($command);
$onlyWebTickets = array_unique(
array_filter(
$onlyWebTickets,
function ($value) {
return !empty($value);
}
)
);

return $onlyWebTickets;
}

/**
Expand All @@ -216,7 +279,7 @@ private function preparePayloadAndSendToConfluence()
],
];

$response = $this->client->request(
$response = $this->getClient()->request(
'PUT',
$this->pageId,
[
Expand All @@ -225,7 +288,7 @@ private function preparePayloadAndSendToConfluence()
);

if ($response->getStatusCode() !== self::HTTP_OK) {
throw new Exception('Could not send new version');
$this->output->writeln('Could not send new version.');
}
}
}
Expand Down
15 changes: 15 additions & 0 deletions bin/console
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env php
<?php

set_time_limit(0);

require __DIR__.'/../vendor/autoload.php';

use Basilicom\ReleaseNotesBundle\Command\ReleaseNotesPublisherCommand;
use Symfony\Component\Console\Application;

$application = new Application('echo', '1.0.0');
$command = new ReleaseNotesPublisherCommand('', '', '', '');

$application->add($command);
$application->run();

0 comments on commit 1020e6e

Please sign in to comment.