mirror of
https://gh.wpcy.net/https://github.com/discourse/discourse.git
synced 2026-05-09 03:18:53 +08:00
I wanted a better way to show a live/up-to-date status of a PR than what the https://github.com/discourse/github-status-theme provided. First, I wanted it to work on any PR, including ones in private repositories. Second, I wanted to include the approved status, which requires a 2nd call to GitHub's API. Third, I wanted something that was less "intrusive" than the "shield-like" status, so I opted out to use the icons & color that GitHub uses (but maybe that's a bad idea). After a first PoC that was a dump proxy to handle authentication for private repositories, the idea to use org webhooks was raised and turned out to be much lighter and easier than figuring out a proper caching strategy. So this adds support for receiving `pull_request` and `pull_request_review` webhooks events to schedule a background job that will rebake posts and chat messages that have a link to the mentioned PR. The GitHub PR onebox has been updated to query and parse the review state so we can have a better icon. This also adds the `Chat::MessageLink` model (that is the #chat version of `TopicLink`) to help better keep track of links posted in chat. **BEFORE** <img width="1525" height="1356" alt="BEFORE" src="https://github.com/user-attachments/assets/02f66137-9f4f-4a91-b321-73816161e204" /> **AFTER** <img width="1525" height="1356" alt="AFTER" src="https://github.com/user-attachments/assets/2164b7ef-8cd0-4cec-aea8-936a76a94fb2" /> Internal ref - t/17138
41 lines
1.1 KiB
Ruby
41 lines
1.1 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module DiscourseGithub
|
|
class WebhooksController < ::ApplicationController
|
|
requires_plugin "discourse-github"
|
|
|
|
skip_before_action :check_xhr
|
|
skip_before_action :verify_authenticity_token
|
|
skip_before_action :redirect_to_login_if_required
|
|
|
|
def github
|
|
return head :forbidden unless verify_signature
|
|
|
|
event = request.headers["X-GitHub-Event"]
|
|
return head :ok if %w[pull_request pull_request_review].exclude?(event)
|
|
|
|
pr_url = params.dig(:pull_request, :html_url)
|
|
return head :ok if pr_url.blank?
|
|
|
|
Jobs.enqueue(:rebake_github_pr_posts, pr_url: pr_url)
|
|
|
|
head :ok
|
|
end
|
|
|
|
private
|
|
|
|
def verify_signature
|
|
secret = SiteSetting.github_webhook_secret
|
|
return false if secret.blank?
|
|
|
|
signature = request.headers["X-Hub-Signature-256"]
|
|
return false if signature.blank?
|
|
|
|
request.body.rewind
|
|
body = request.body.read
|
|
expected = "sha256=" + OpenSSL::HMAC.hexdigest("SHA256", secret, body)
|
|
|
|
ActiveSupport::SecurityUtils.secure_compare(expected, signature)
|
|
end
|
|
end
|
|
end
|