Skip to content

Commit a6f4136

Browse files
authored
feat(dev): add webhook check to release compliance (#9144)
1 parent 495f609 commit a6f4136

2 files changed

Lines changed: 63 additions & 34 deletions

File tree

.github/workflows/release-checks.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,4 +152,5 @@ jobs:
152152
- name: "Check repo compliance"
153153
env:
154154
GH_TOKEN: ${{ secrets.SPLIT_TOKEN }}
155-
run: ./dev/google-cloud repo:compliance --format=ci -t $GH_TOKEN
155+
PG_TOKEN: ${{ secrets.PACKAGIST_SAFE_TOKEN }}
156+
run: ./dev/google-cloud repo:compliance --format=ci -t $GH_TOKEN -p $PG_TOKEN

dev/src/Command/RepoComplianceCommand.php

Lines changed: 61 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ protected function configure()
4949
->addOption('component', 'c', InputOption::VALUE_REQUIRED, 'If specified, display repo info for this component only', '')
5050
->addOption('token', 't', InputOption::VALUE_REQUIRED, 'Github token to use for authentication', '')
5151
->addOption('format', 'f', InputOption::VALUE_REQUIRED, 'can be "ci" or "table"', 'table')
52-
->addOption('new-packagist-token', '', InputOption::VALUE_REQUIRED, 'update the packagist token')
52+
->addOption('packagist-token', 'p', InputOption::VALUE_REQUIRED, 'Packagist token for the webhook')
5353
;
5454
}
5555

@@ -58,7 +58,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
5858
// Create github client wrapper
5959
$http = new Client();
6060
$this->github = new GitHub(new RunShell(), $http, $input->getOption('token'), $output);
61-
$this->packagist = new Packagist($http, self::PACKAGIST_USERNAME, $input->getOption('new-packagist-token') ?? '');
61+
$this->packagist = new Packagist($http, self::PACKAGIST_USERNAME, $input->getOption('packagist-token') ?? '');
6262

6363
$format = $input->getOption('format');
6464
if (!in_array($format, ['ci', 'table'])) {
@@ -82,48 +82,38 @@ protected function execute(InputInterface $input, OutputInterface $output)
8282

8383
$isCompliant = true;
8484
foreach ($components as $i => $component) {
85-
$details = $this->getRepoDetails($component);
86-
$settingsCheck = true;
87-
$packagistCheck = true;
88-
$teamCheck = true;
89-
90-
$refreshDetails = false;
91-
if (!$this->checkSettingsCompliance($details)) {
92-
$settingsCheck = false;
93-
$refreshDetails |= $this->askFixSettingsCompliance($input, $output, $details);
94-
}
95-
if (!$this->checkPackagistCompliance($details)) {
96-
$packagistCheck = false;
97-
$refreshDetails |= $this->askFixPackagistCompliance($input, $output, $component->getRepoName());
98-
}
99-
if (!$this->checkTeamCompliance($details)) {
100-
$teamCheck = $this->github->token ? false : null;
101-
$refreshDetails |= $this->askFixTeamCompliance($input, $output, $component->getRepoName());
102-
}
103-
if ($refreshDetails) {
85+
do {
10486
$details = $this->getRepoDetails($component);
105-
}
106-
if ($packagistToken = $this->packagist->getApiToken()) {
107-
$repoName = 'googleapis/' . $details['name'];
108-
$webhookUrl = $this->packagist->getWebhookUrl();
109-
if (!$webhookId = $this->github->getWebhook($repoName, $webhookUrl, $packagistToken)) {
110-
$output->writeln(sprintf('<error>%s</error>: Webhook not found in', $repoName));
111-
} elseif (!$this->github->updateWebhook($repoName, $webhookId, $packagistToken, $webhookUrl)) {
112-
$output->writeln(sprintf('<error>%s</error>: Unable to update webhook.', $repoName));
113-
} else {
114-
$output->writeln(sprintf('<comment>%s</comment>: Packagist webhook token updated.', $repoName));
87+
$settingsCheck = $packagistCheck = $webhookCheck = $teamCheck = true;
88+
$refreshDetails = false;
89+
if (!$this->checkSettingsCompliance($details)) {
90+
$settingsCheck = false;
91+
$refreshDetails |= $this->askFixSettingsCompliance($input, $output, $details);
11592
}
116-
}
93+
if (!$this->checkWebhookCompliance($details)) {
94+
$webhookCheck = false;
95+
$refreshDetails |= $this->askFixWebhookCompliance($input, $output, $details);
96+
}
97+
if (!$this->checkPackagistCompliance($details)) {
98+
$packagistCheck = false;
99+
$refreshDetails |= $this->askFixPackagistCompliance($input, $output, $component->getRepoName());
100+
}
101+
if (!$this->checkTeamCompliance($details)) {
102+
$teamCheck = $this->github->token ? false : null;
103+
$refreshDetails |= $this->askFixTeamCompliance($input, $output, $component->getRepoName());
104+
}
105+
} while ($refreshDetails);
117106

118107
$emoji = fn (?bool $check) => match ($check) { null => '', true => '', false => ''};
119108
$details['compliant'] = implode("\n", [
120109
sprintf('%s Issues, Projects, Wiki, Pages, and Discussion are disabled', $emoji($settingsCheck)),
110+
sprintf('%s Packagist webhook is configured', $emoji($webhookCheck)),
121111
sprintf('%s Packagist maintainer is "google-cloud"', $emoji($packagistCheck)),
122112
sprintf('%s Github teams permissions are configured correctly', $emoji($teamCheck)),
123113
'',
124114
]);
125115

126-
$isCompliant = $isCompliant && $settingsCheck && $packagistCheck && $teamCheck;
116+
$isCompliant &= $settingsCheck && $webhookCheck && $packagistCheck && $teamCheck;
127117
if ($format == 'ci') {
128118
unset($details['repo_config'], $details['packagist_config'], $details['teams']);
129119
}
@@ -177,6 +167,44 @@ private function askFixSettingsCompliance(InputInterface $input, OutputInterface
177167
return false;
178168
}
179169

170+
private function checkWebhookCompliance(array $details): bool
171+
{
172+
$repoName = 'googleapis/' . $details['name'];
173+
$webhookUrl = $this->packagist->getWebhookUrl();
174+
175+
return null !== $this->github->getWebhook($repoName, $webhookUrl);
176+
}
177+
178+
private function askFixWebhookCompliance(InputInterface $input, OutputInterface $output, array $details)
179+
{
180+
if (!$this->github->token || $input->getOption('format') == 'ci') {
181+
// without a token, or in CI mode, don't ask to fix compliance
182+
return false;
183+
}
184+
185+
$question = new ConfirmationQuestion(sprintf(
186+
'Repo %s does not have the packagist webhook configured. Would you like to configure it? (Y/n)',
187+
$details['name'],
188+
), true);
189+
if ($this->getHelper('question')->ask($input, $output, $question)) {
190+
if (!$packagistToken = $this->packagist->getApiToken()) {
191+
throw new \Exception('Packagist token required to update webhook compliance');
192+
}
193+
194+
$repoName = 'googleapis/' . $details['name'];
195+
$webhookUrl = $this->packagist->getWebhookUrl();
196+
if (!$this->github->addWebhook($repoName, $webhookUrl, $packagistToken)) {
197+
$output->writeln(sprintf('<error>%s</error>: Unable to create Packagist webhook.', $repoName));
198+
199+
return false;
200+
}
201+
$output->writeln(sprintf('<comment>%s</comment>: Packagist webhook created.', $repoName));
202+
return true;
203+
}
204+
205+
return false;
206+
}
207+
180208
private function checkPackagistCompliance(array $details)
181209
{
182210
return !empty(array_filter(

0 commit comments

Comments
 (0)