php 删除Gitlab项目的所有合并分支。生的
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了php 删除Gitlab项目的所有合并分支。生的相关的知识,希望对你有一定的参考价值。
#!/usr/bin/env php
<?php
/**
* Gitlab offers the ability to remove all branches in a projects that have
* already been merged to master. However, as project count grows, it can become
* cumbersome to visit each project an press that "delete" button.
*
* This script automated that task.
*
* When given the URL for a Gitlab REST API and a api-token, this script will
* fetch a list of all projects (that are not archived and do not belong to a user)
* and remove all branches that have already been merged to master.
*
* Requires PHP 5.4 or higher to run
*/
set_error_handler(function ($severity, $message, $file, $line) {
throw new ErrorException($message, 0, $severity, $file, $line);
});
/**
* @param array $arguments
*
* @return int The exit code
*/
function run(array $arguments)
{
$exitCode = 1;
$logger = new Logger();
if (count($arguments) !== 3) {
$message = vsprintf('Usage: %s <gitlab-domain> <api-token>', [$arguments[0]]);
$logger->error($message);
$exitCode = 64;
} else {
array_shift($arguments);
list($domain, $apiToken) = $arguments;
$url = vsprintf('https://%s/api/%s/', [$domain, 'v4']);
$message = vsprintf(' ====> Removing all merged branches for non-archived, non-user projects at "%s"', [$url]);
$logger->info($message);
try {
$api = new GitlabApi($url, $apiToken, $logger);
$api->removeAllMergedBranches();
$exitCode = 0;
} catch (\Exception $exception) {
$message = vsprintf(' ! ERROR An %s occurred: %s (line %s)', [get_class($exception), $exception->getMessage(), $exception->getLine()]);
if (strpos($exception->getMessage(), 'certificate verify failed') !== false) {
$message .= "\n".'This issue might be solved by this solution: https://stackoverflow.com/a/29405127/153049';
}
$logger->error("\n".$message);
$exitCode = 65;
}
}
return $exitCode;
}
/**
* Class to Log to the CLI
*/
class Logger
{
final public function info($message)
{
$this->log(STDOUT, $message);
}
final public function error($message)
{
$this->log(STDERR, $message);
}
private function log($handle, $message)
{
fwrite($handle, $message.PHP_EOL);
}
}
/**
* Class to communicate with the Gitlab REST API
*/
class GitlabApi
{
const HTTP_STATUS_PATTERN = '/^.* (?<CODE>[0-9]{3}) (?<STATUS>.*)$/';
/** @var string */
private $api;
/** @var Logger */
private $logger;
/** @var string */
private $token;
/** @var bool */
private $urlIsUsable;
/**
* @param string $api
* @param string $token
* @param Logger $logger
*/
final public function __construct($api, $token, Logger $logger)
{
$this->api = $api;
$this->logger = $logger;
$this->token = $token;
}
/**
* @throws \RuntimeException
*/
final public function removeAllMergedBranches()
{
$projects = $this->fetchProjects();
$this->removeMergedBranches($projects);
}
/**
* @param $method
* @param $path
*
* @return bool|string
*
* @throws \RuntimeException
*/
private function call($method, $path) {
$this->validateApiUrl();
return file_get_contents($this->api.$path, false, $this->getStreamContext($method));
}
/**
* @param string $method
*
* @return resource
*/
private function getStreamContext($method)
{
$contextOptions = [
'http' => [
'method' => $method,
'header' => 'PRIVATE-TOKEN: '.$this->token
]
];
return stream_context_create($contextOptions);
}
/**
* @return array
*
* @throws \RuntimeException
*/
private function fetchProjects()
{
$this->logger->info(' ====> Fetching project list');
$path = '/projects?archived=false&per_page=100';
$response = $this->call('GET', $path);
$projectLists = json_decode($response, true);
$projects = [];
array_walk($projectLists, function ($project) use (&$projects) {
if ($project['archived'] === false && $project['namespace']['kind'] === 'group') {
$name = $project['path_with_namespace'];
$projects[$name] = $project['id'];
}
});
ksort($projects);
return $projects;
}
/**
* @param array $projects
*
* @throws \RuntimeException
*/
private function removeMergedBranches(array $projects)
{
array_walk($projects, function ($id, $name) {
$message = vsprintf(' ----> Removing all merged branches for: "%s" (id:%d)', [$name, $id]);
$this->logger->info($message);
$url = vsprintf('/projects/%s/repository/merged_branches', [$id]);
try {
$this->call('DELETE', $url);
} catch (\ErrorException $exception) {
preg_match(self::HTTP_STATUS_PATTERN, $exception->getMessage(), $matches);
$message = vsprintf(' Could not remove branches for "%s": %s (%d)', [
$name,
$matches['STATUS'],
$matches['CODE'],
]);
$this->logger->error($message);
}
});
}
/**
* @throws \RuntimeException
*/
private function validateApiUrl()
{
if ($this->urlIsUsable === null) {
$streamContext = $this->getStreamContext('GET');
if (PHP_MAJOR_VERSION >= 7 && PHP_MINOR_VERSION >= 1) {
$headers = get_headers($this->api . '/version', true, $streamContext);
} else {
$options = stream_context_get_options($streamContext);
stream_context_set_default($options);
$headers = get_headers($this->api . '/version', true);
}
if (PHP_MAJOR_VERSION >= 7 || (PHP_MAJOR_VERSION === 5 && PHP_MINOR_VERSION >= 6)) {
$headers = array_filter($headers, 'is_int', ARRAY_FILTER_USE_KEY);
} else {
$keys = array_filter(array_keys($headers), 'is_string');
$headers = array_diff_key($headers, array_flip($keys));
}
$statusHeader = array_pop($headers);
preg_match(self::HTTP_STATUS_PATTERN, $statusHeader, $matches);
$this->urlIsUsable = ($matches['CODE'] >= 200 && $matches['CODE'] <= 299);
if ($this->urlIsUsable !== true) {
$message = vsprintf('Could not connect to API at %s. Got non-OK response: %s (%d)', [
$this->api,
$matches['STATUS'],
$matches['CODE'],
]);
throw new \RuntimeException($message);
}
}
}
}
exit(run($argv));
/*EOF*/
以上是关于php 删除Gitlab项目的所有合并分支。生的的主要内容,如果未能解决你的问题,请参考以下文章