iwink / gitlab-webhook-bundle
一个用于处理GitLab webhooks的Symfony扩展包。
Requires
- php: >=7.4
- ext-json: *
- doctrine/annotations: ^1.11|^2.0
- symfony/config: ^5.0|^6.0
- symfony/dependency-injection: ^5.0|^6.0
- symfony/http-kernel: ^5.0|^6.0
- symfony/yaml: ^5.0|^6.0
Requires (Dev)
- phpunit/phpunit: ^9.4
- roave/security-advisories: dev-latest
README
一个用于处理GitLab webhooks的Symfony扩展包。
安装
要使用此扩展包,请使用Composer进行安装:composer require iwink/gitlab-webhook-bundle。如果您的项目使用Symfony Flex,则已完成。如果没有,请确保在项目的config/bundles.php中启用扩展包。
用法
要将控制器标记为GitLab webhook,您可以在控制器上方使用@Webhook(event="event")注释,并在方法中定义一个Iwink\GitLabWebhookBundle\Event\WebhookEvent参数
<?php namespace App\Controller; use Iwink\GitLabWebhookBundle\Annotation\Webhook; use Iwink\GitLabWebhookBundle\Event\PipelineEvent; use Iwink\GitLabWebhookBundle\Scheduler; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\Routing\Annotation\Route; /** * @Route("/webhook", name="webhook_") */ class WebhookController { /** * @Route("/pipeline", name="pipeline") * @Webhook("pipeline") */ public function pipeline(PipelineEvent $event, Scheduler $scheduler): JsonResponse { $status = $event->getObjectAttributes()['status']; if ('success' === $status) { $scheduler->schedule([$this, 'expensiveOperation'], ['one', true]); } return new JsonResponse(); } public function expensiveOperation(string $name, bool $valid): void { // Does something expensive } }
上面的示例使用@Webhook("pipeline")注释将pipeline方法标记为webhook,该webhook接收一个Pipeline Hook事件。事件通过方法参数的$event注入,注入基于参数的类型提示(PipelineEvent),参数名称不重要。因为GitLab期望尽快得到响应,所以webhook的昂贵部分在发送响应后由Iwink\GitLabWebhookBundle\Scheduler::schedule()方法调度和执行。
安全的webhooks
GitLab可以选择使用secret token来保护webhook。您可以在webhook注释中定义这些secret tokens
<?php namespace App\Controller; use Iwink\GitLabWebhookBundle\Annotation\Webhook; use Iwink\GitLabWebhookBundle\Event\PipelineEvent; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\Routing\Annotation\Route; /** * @Route("/webhook", name="webhook_") */ class WebhookController { /** * @Route("/pipeline", name="pipeline") * @Webhook("pipeline", tokens={"secret_token"}) */ public function pipeline(PipelineEvent $event): JsonResponse { // Handle request } }
现在接收到的Pipeline Hook请求应包含secret token(由X-GitLab-Token头提供),否则请求失败。由于可能为同一注释定义多个tokens(因为多个GitLab项目可能触发相同的webhook),因此tokens应定义为数组。tokens也可以使用%parameter.name%格式作为配置参数定义:@Webhook("pipeline", tokens={"%gitlab.secret_token%"})。由于参数可以包含环境变量,因此配置秘密非常灵活。
注意事项
由于Symfony缓存注释,并且定义注释的文件在更新参数时没有改变,因此在更改秘密参数值后,您应该手动清除缓存。这只会发生在dev环境中,因为在prod环境中容器始终被缓存(每次您的代码更改,您都需要清除缓存)。
多个webhooks
可以使用多个@Webhook注释将多个webhooks注册到单个控制器中
<?php namespace App\Controller; use Iwink\GitLabWebhookBundle\Annotation\Webhook; use Iwink\GitLabWebhookBundle\Event\MergeRequestEvent; use Iwink\GitLabWebhookBundle\Event\PushEvent; use Iwink\GitLabWebhookBundle\Event\WebhookEvent; use Iwink\GitLabWebhookBundle\Scheduler; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\Routing\Annotation\Route; /** * @Route("/webhook", name="webhook_") */ class WebhookController { /** * @Route("/pipeline", name="pipeline") * @Webhook("push") * @Webhook(event="merge request") */ public function pipeline(WebhookEvent $event, Scheduler $scheduler): JsonResponse { if ( ($event instanceof PushEvent && 'some/project' === $event->getProject()['name']) || ($event instanceof MergeRequestEvent && 'success' === $event->getObjectAttributes()['status']) ) { $scheduler->schedule([$this, 'expensiveOperation']); } return new JsonResponse(); } public function expensiveOperation(): void { // Does something expensive } }
注入的$event现在是Iwink\GitLabWebhookBundle\Event\PushEvent或Iwink\GitLabWebhookBundle\Event\MergeRequestEvent。注意两个@Webhook注释之间的区别,短(@Webhook("push"))和长(@Webhook(event="merge request"))语法给出相同的结果,所以使用哪种语法都无关紧要。
支持的webhooks
以下webhooks被支持
- 评论 (
Iwink\GitLabWebhookBundle\Event\CommentEvent) - 部署 (
Iwink\GitLabWebhookBundle\Event\DeploymentEvent) - 功能标志 (
Iwink\GitLabWebhookBundle\Event\FeatureFlagEvent) - 问题 (
Iwink\GitLabWebhookBundle\Event\IssueEvent) - 作业 (
Iwink\GitLabWebhookBundle\Event\JobEvent) - 合并请求 (
Iwink\GitLabWebhookBundle\Event\MergeRequestEvent) - 管道 (
Iwink\GitLabWebhookBundle\Event\PipelineEvent) - 推送 (
Iwink\GitLabWebhookBundle\Event\PushEvent) - 发布 (
Iwink\GitLabWebhookBundle\Event\ReleaseEvent) - 系统 (
Iwink\GitLabWebhookBundle\Event\SystemEvent) - 标签 (
Iwink\GitLabWebhookBundle\Event\TagEvent) - 维基页面 (
Iwink\GitLabWebhookBundle\Event\WikiPageEvent)