Skip to content

Instantly share code, notes, and snippets.

@ryancwalsh
Created August 26, 2018 21:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryancwalsh/6f61ab68d8331e5810c955fa2700ea11 to your computer and use it in GitHub Desktop.
Save ryancwalsh/6f61ab68d8331e5810c955fa2700ea11 to your computer and use it in GitHub Desktop.
Export all BitBucket issues to json file
<?php
/**
* EXPORT ALL BITBUCKET ISSUES TO JSON FILE
*
* I couldn't figure out how to use https://github.com/GrahamCampbell/Laravel-Bitbucket/ so instead am using https://github.com/BitbucketAPI/Client/ directly so that I can export (download) all of my issues from all of my Bitbucket repositories' issue trackers.
*
* Here are the steps that make it work:
*
* 1. Visit https://bitbucket.org/account/user/{your_username}/app-passwords
* 2. Click "Create app password", and enable "Read" access to all of the following: "Account", "Issues", "Projects", "Repositories".
* When I tried granting access to just Issues, I got this misleading error: Symfony\Component\Debug\Exception\FatalThrowableError : strtok() expects parameter 1 to be string, array given
* 3. In your .env file, paste the username and password like this:
*
BITBUCKET_USERNAME=johndoe
BITBUCKET_PASSWORD=mmnb54m5nb4mn5b64
*
* 4. Create a config/bitbucket.php file that has this:
*
* return [
'username' => env('BITBUCKET_USERNAME'),
'password' => env('BITBUCKET_PASSWORD'), //You will visit https://bitbucket.org/account/user/{your_username}/app-passwords and then paste into your .env file
];
*
* 5. Run `composer require bitbucket/client`
* 6. Now you can use a function like what I wrote for getJsonOfAllIssues() below.
*
*/
namespace App\Console\Commands;
use Bitbucket\Client;
use Illuminate\Console\Command;
use Storage;
class DownloadBitbucketIssues extends Command {
const FILENAME = 'issues.json';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'downloadBitbucketIssues';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Use the Bitbucket API to download all the issues for backup purposes.';
public function __construct() {
parent::__construct();
}
public function handle() {
$issuesAcrossAllRepos = $this->getJsonOfAllIssues();
Storage::disk('local')->put(self::FILENAME, json_encode($issuesAcrossAllRepos));
$this->info('Saved json of all issues to file: ' . self::FILENAME);
//TODO: save file to Amazon S3 too (maybe using https://docs.spatie.be/laravel-backup/v5/introduction)
}
/**
*
* @return string
*/
public function getJsonOfAllIssues() {
$username = config('bitbucket.username');
$c = new Client();
$c->authenticate(Client::AUTH_HTTP_PASSWORD, $username, config('bitbucket.password'));
$reposResult = $c->repositories()->users($username)->list(['pagelen' => 100]); //Any account with more than 100 repos will need to edit this code to use pagination instead.
$repoNames = [];
foreach ($reposResult['values'] as $repoDetails) {
$repoNames[] = $repoDetails['name'];
}
$this->info('Found these repos and will now look to download their issues: ' . json_encode($repoNames));
$namesOfReposWithIssueTracker = [];
$issueCounts = [];
foreach ($reposResult['values'] as $repoDetails) {
$links = $repoDetails['links'];
if (isset($links['issues'])) {
$namesOfReposWithIssueTracker[] = $repoDetails['name'];
$issueCounts[$repoDetails['name']] = 0;
}
}
$issuesAcrossAllRepos = [];
foreach ($namesOfReposWithIssueTracker as $repoName) {
$issuesForThisRepo = [];
$page = 1;
do {
$resultsForPage = $c->repositories()->users($username)->issues($repoName)->list(['pagelen' => 100, 'page' => $page]); //100 is max: https://developer.atlassian.com/bitbucket/api/2/reference/resource/repositories/%7Busername%7D/%7Brepo_slug%7D/issues
$numResultsOnThisPage = count($resultsForPage['values']);
$this->info($repoName . ' page ' . $page . ' has this many results: ' . $numResultsOnThisPage);
$issuesForThisRepo = array_merge($issuesForThisRepo, $resultsForPage['values']);
$issueCounts[$repoName] += $numResultsOnThisPage;
$page++;
} while (isset($resultsForPage['next']));
$issuesAcrossAllRepos[$repoName] = $issuesForThisRepo;
}
$this->info('Number of issues per repo: ' . json_encode($issueCounts));
return $issuesAcrossAllRepos;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment