Created
February 19, 2020 19:23
-
-
Save rieschl/fb5a404e1521920dcbe62ec0ba1dc733 to your computer and use it in GitHub Desktop.
Update Github Secrets on all Repos
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
use GuzzleHttp\Client; | |
use Psr\Http\Message\ResponseInterface; | |
use function GuzzleHttp\Psr7\parse_header; | |
require 'vendor/autoload.php'; | |
$baseUri = 'https://api.github.com/'; | |
$ghUsername = 'user'; | |
$ghToken = 'token'; | |
$secrets = [ | |
'SECRET_NAME' => 'secret value', | |
'SECRET_TWO' => 'even more secret', | |
]; | |
$uri = $baseUri . 'orgs/eventjet/repos'; | |
while ($uri !== null) { | |
[$repos, $next] = fetchRepos($uri); | |
if ($next === null) { | |
$uri = null; | |
} else { | |
$uri = $next; | |
} | |
foreach ($repos as $repo) { | |
echo $repo['full_name'] . "\n"; | |
setRepositorySecrets($repo['full_name'], $secrets); | |
} | |
} | |
function fetchRepos(string $uri) | |
{ | |
global $ghUsername, $ghToken; | |
$client = new Client(); | |
$response = $client->get($uri, ['auth' => [$ghUsername, $ghToken],]); | |
$repos = (string)$response->getBody(); | |
$repos = json_decode($repos, true); | |
$next = getNextLink($response); | |
return [$repos, $next]; | |
} | |
function getNextLink(ResponseInterface $response): ?string | |
{ | |
$link = parse_header($response->getHeader('Link')); | |
foreach ($link as $item) { | |
if ($item['rel'] === 'next') { | |
return substr($item[0], 1, -1); | |
} | |
} | |
return null; | |
} | |
/** | |
* @param array<string, string> $secrets | |
*/ | |
function setRepositorySecrets(string $repo, array $secrets) | |
{ | |
$key = fetchKey($repo); | |
foreach ($secrets as $secretName => $secretValue) { | |
setSecret($repo, $secretName, $secretValue, $key); | |
} | |
} | |
/** | |
* @param array{key: string, key_id: string} $key | |
*/ | |
function setSecret(string $repo, string $secretName, string $secretValue, array $key) | |
{ | |
global $baseUri, $ghUsername, $ghToken; | |
$client = new Client(['base_uri' => $baseUri]); | |
$encryptedValue = encryptSecret($key['key'], $secretValue); | |
$client->put( | |
'repos/' . $repo . '/actions/secrets/' . $secretName, | |
[ | |
'auth' => [$ghUsername, $ghToken], | |
'json' => ['key_id' => $key['key_id'], 'encrypted_value' => $encryptedValue], | |
] | |
); | |
} | |
function encryptSecret(string $key, string $message): string | |
{ | |
$binKey = base64_decode($key); | |
$encrypted = sodium_crypto_box_seal($message, $binKey); | |
return base64_encode($encrypted); | |
} | |
/** | |
* @return array{key: string, key_id: string} | |
*/ | |
function fetchKey(string $repo): array | |
{ | |
global $baseUri, $ghUsername, $ghToken; | |
$client = new Client(['base_uri' => $baseUri]); | |
$response = $client->get( | |
'repos/' . $repo . '/actions/secrets/public-key', | |
['auth' => [$ghUsername, $ghToken]] | |
); | |
return json_decode((string)$response->getBody(), true); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment