diff --git a/administrator/components/com_patchtester/patchtester.xml b/administrator/components/com_patchtester/patchtester.xml
index fc27eac..8b0347d 100644
--- a/administrator/components/com_patchtester/patchtester.xml
+++ b/administrator/components/com_patchtester/patchtester.xml
@@ -7,7 +7,7 @@
GNU General Public License version 2 or later
admin@joomla.org
https://www.joomla.org
- 3.0.0.dev
+ 3.0.0-dev
COM_PATCHTESTER_XML_DESCRIPTION
script.php
diff --git a/build/patchtester/release.php b/build/patchtester/release.php
new file mode 100755
index 0000000..59d1720
--- /dev/null
+++ b/build/patchtester/release.php
@@ -0,0 +1,122 @@
+#!/usr/bin/env php
+ --exclude-manifest
+ *
+ * Examples:
+ * - php build/patchtester/release.php -v 3.0.0
+ * - php build/patchtester/release.php -v 3.0.1-dev --exclude-manifest
+ *
+ * @copyright Copyright (C) 2011 - 2012 Ian MacLennan, Copyright (C) 2013 - 2016 Open Source Matters, Inc. All rights reserved.
+ * @license GNU General Public License version 2 or later
+ */
+
+// Constants.
+const PHP_TAB = "\t";
+
+// Functions.
+function usage($command)
+{
+ echo PHP_EOL;
+ echo 'Usage: php ' . $command . ' [options]' . PHP_EOL;
+ echo PHP_TAB . '[options]:'.PHP_EOL;
+ echo PHP_TAB . PHP_TAB . '-v :' . PHP_TAB . 'Version (ex: 3.0.0, 3.0.1-dev)' . PHP_EOL;
+ echo PHP_TAB . PHP_TAB . '--exclude-manifest: Exclude updating the update server manifest';
+ echo PHP_EOL;
+}
+
+$manifestFile = '/administrator/components/com_patchtester/patchtester.xml';
+$updateServerFile = '/manifest.xml';
+
+// Check arguments (exit if incorrect cli arguments).
+$opts = getopt('v:', array('exclude-manifest'));
+
+if (empty($opts['v']))
+{
+ usage($argv[0]);
+ die();
+}
+
+// Check version string (exit if not correct).
+$versionParts = explode('-', $opts['v']);
+
+if (!preg_match('#^[0-9]+\.[0-9]+\.[0-9]+$#', $versionParts[0]))
+{
+ usage($argv[0]);
+ die();
+}
+
+if (isset($versionParts[1]) && !preg_match('#(dev|alpha|beta|rc)[0-9]*#', $versionParts[1]))
+{
+ usage($argv[0]);
+ die();
+}
+
+if (isset($versionParts[2]) && $versionParts[2] !== 'dev')
+{
+ usage($argv[0]);
+ die();
+}
+
+// Make sure we use the correct language and timezone.
+setlocale(LC_ALL, 'en_GB');
+date_default_timezone_set('Europe/London');
+
+// Make sure file and folder permissions are set correctly.
+umask(022);
+
+// Set version properties.
+$versionSubParts = explode('.', $versionParts[0]);
+
+$version = array(
+ 'main' => $versionSubParts[0] . '.' . $versionSubParts[1],
+ 'release' => $versionSubParts[0] . '.' . $versionSubParts[1] . '.' . $versionSubParts[2],
+ 'dev_devel' => $versionSubParts[2] . (!empty($versionParts[1]) ? '-' . $versionParts[1] : '') . (!empty($versionParts[2]) ? '-' . $versionParts[2] : ''),
+ 'credate' => date('d-F-Y'),
+);
+
+// Prints version information.
+echo PHP_EOL;
+echo 'Version data:'. PHP_EOL;
+echo '- Main:' . PHP_TAB . PHP_TAB . PHP_TAB . $version['main'] . PHP_EOL;
+echo '- Release:' . PHP_TAB . PHP_TAB . $version['release'] . PHP_EOL;
+echo '- Full:' . PHP_TAB . PHP_TAB . PHP_TAB . $version['main'] . '.' . $version['dev_devel'] . PHP_EOL;
+echo '- Dev Level:' . PHP_TAB . PHP_TAB . $version['dev_devel'] . PHP_EOL;
+echo '- Creation date:' . PHP_TAB . $version['credate'] . PHP_EOL;
+echo PHP_EOL;
+
+$rootPath = dirname(dirname(__DIR__));
+
+// Updates the version and creation date in the component manifest file.
+if (file_exists($rootPath . $manifestFile))
+{
+ $fileContents = file_get_contents($rootPath . $manifestFile);
+ $fileContents = preg_replace('#[^<]*#', '' . $version['main'] . '.' . $version['dev_devel'] . '', $fileContents);
+ $fileContents = preg_replace('#[^<]*#', '' . $version['credate'] . '', $fileContents);
+ file_put_contents($rootPath . $manifestFile, $fileContents);
+}
+
+// Replaces the `__DEPLOY_VERSION__` marker with the "release" version number
+system('cd ' . $rootPath . ' && find administrator -name "*.php" -type f -exec sed -i "" "s/__DEPLOY_VERSION__/' . $version['release'] . '/g" "{}" \;');
+
+// If not instructed to exclude it, update the update server's manifest
+if (!isset($opts['exclude-manifest']))
+{
+ if (file_exists($rootPath . $updateServerFile))
+ {
+ $fileContents = file_get_contents($rootPath . $updateServerFile);
+ $fileContents = preg_replace('#[^<]*#', 'https://github.com/joomla-extensions/patchtester/releases/tag/' . $version['release'] . '', $fileContents);
+ $fileContents = preg_replace('#[^<]*#', 'https://github.com/joomla-extensions/patchtester/releases/download/' . $version['release'] . '/com_patchtester.zip', $fileContents);
+ file_put_contents($rootPath . $updateServerFile, $fileContents);
+ }
+}
+
+echo 'Version bump complete!' . PHP_EOL;