mirror of
https://github.com/czhu12/canine.git
synced 2026-01-31 08:29:53 -06:00
commenting
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
class ProjectForks::Create
|
||||
extend LightService::Organizer
|
||||
|
||||
def self.call(parent_project:, pull_request:)
|
||||
def self.call(parent_project:, pull_request:, current_user:)
|
||||
with(parent_project:, pull_request:).reduce(
|
||||
ProjectForks::ForkProject,
|
||||
ProjectForks::InitializeFromCanineConfig,
|
||||
ProjectForks::PostForkComment
|
||||
execute(->(ctx) { ctx[:project] = ctx.project_fork.child_project }).
|
||||
Projects::DeployLatestCommit,
|
||||
ProjectForks::PostForkComment,
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,30 +4,6 @@ class ProjectForks::PostForkComment
|
||||
|
||||
executed do |context|
|
||||
project_fork = context.project_fork
|
||||
parent_project = project_fork.parent_project
|
||||
|
||||
client = Git::Client.from_project(parent_project)
|
||||
comment_body = build_comment_body(project_fork)
|
||||
client.add_pull_request_comment(project_fork.number, comment_body)
|
||||
rescue StandardError => e
|
||||
Rails.logger.error("Failed to post fork comment: #{e.message}")
|
||||
# Don't fail the entire workflow if comment posting fails
|
||||
end
|
||||
|
||||
def self.build_comment_body(project_fork)
|
||||
project_url = Rails.application.routes.url_helpers.project_url(project_fork.child_project)
|
||||
|
||||
<<~COMMENT
|
||||
🚀 **Preview environment created!**
|
||||
|
||||
A preview environment has been created for this pull request.
|
||||
|
||||
**Project:** [#{project_fork.child_project.name}](#{project_url})
|
||||
|
||||
The deployment is in progress. Once complete, you'll be able to access the preview at the project link above.
|
||||
|
||||
---
|
||||
*Deployed by [Canine](#{Rails.application.routes.url_helpers.root_url})*
|
||||
COMMENT
|
||||
ProjectForks::PostCommentJob.perform_later(project_fork)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -60,7 +60,8 @@ class Projects::ProjectForksController < Projects::BaseController
|
||||
|
||||
result = ProjectForks::Create.call(
|
||||
parent_project: @project,
|
||||
pull_request:
|
||||
pull_request:,
|
||||
current_user:
|
||||
)
|
||||
if result.success?
|
||||
Projects::DeployLatestCommit.execute(project: result.project_fork.child_project, current_user:)
|
||||
|
||||
70
app/jobs/project_forks/post_comment_job.rb
Normal file
70
app/jobs/project_forks/post_comment_job.rb
Normal file
@@ -0,0 +1,70 @@
|
||||
class ProjectForks::PostCommentJob < ApplicationJob
|
||||
RETRY_DELAY = 30.seconds
|
||||
MAX_ATTEMPTS = 20
|
||||
|
||||
def perform(project_fork, attempt: 1)
|
||||
if certificates_ready?(project_fork)
|
||||
post_comment(project_fork)
|
||||
elsif attempt < MAX_ATTEMPTS
|
||||
self.class.set(wait: RETRY_DELAY).perform_later(project_fork, attempt: attempt + 1)
|
||||
else
|
||||
Rails.logger.warn("ProjectForks::PostCommentJob: Max attempts reached for project_fork #{project_fork.id}, posting comment anyway")
|
||||
post_comment(project_fork)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def certificates_ready?(project_fork)
|
||||
child_project = project_fork.child_project
|
||||
web_services_with_domains = child_project.services.web_service.joins(:domains).distinct
|
||||
|
||||
return true if web_services_with_domains.empty?
|
||||
|
||||
connection = K8::Connection.new(child_project, nil, allow_anonymous: true)
|
||||
|
||||
web_services_with_domains.all? do |service|
|
||||
ingress = K8::Stateless::Ingress.new(service)
|
||||
ingress.connect(connection).certificate_status
|
||||
end
|
||||
rescue StandardError => e
|
||||
Rails.logger.error("ProjectForks::PostCommentJob: Error checking certificate status: #{e.message}")
|
||||
false
|
||||
end
|
||||
|
||||
def post_comment(project_fork)
|
||||
parent_project = project_fork.parent_project
|
||||
client = Git::Client.from_project(parent_project)
|
||||
comment_body = build_comment_body(project_fork)
|
||||
client.add_pull_request_comment(project_fork.number, comment_body)
|
||||
rescue StandardError => e
|
||||
Rails.logger.error("ProjectForks::PostCommentJob: Failed to post comment: #{e.message}")
|
||||
end
|
||||
|
||||
def build_comment_body(project_fork)
|
||||
project_url = Rails.application.routes.url_helpers.project_url(project_fork.child_project)
|
||||
preview_urls = project_fork.urls
|
||||
|
||||
urls_section = if preview_urls.any?
|
||||
urls_list = preview_urls.map { |url| "- #{url}" }.join("\n")
|
||||
<<~URLS
|
||||
|
||||
**Preview URLs:**
|
||||
#{urls_list}
|
||||
URLS
|
||||
else
|
||||
""
|
||||
end
|
||||
|
||||
<<~COMMENT
|
||||
🚀 **Preview environment ready!**
|
||||
|
||||
A preview environment has been deployed for this pull request.
|
||||
|
||||
**Project:** [#{project_fork.child_project.name}](#{project_url})
|
||||
#{urls_section}
|
||||
---
|
||||
*Deployed by [Canine](#{Rails.application.routes.url_helpers.root_url})*
|
||||
COMMENT
|
||||
end
|
||||
end
|
||||
@@ -113,7 +113,7 @@ class Git::Github::Client < Git::Client
|
||||
end
|
||||
|
||||
def add_pull_request_comment(pr_number, body)
|
||||
client.add_comment(repository_url, pr_number, body)
|
||||
client.add_comment(repository_url, pr_number, "[canine] #{body}")
|
||||
end
|
||||
|
||||
def get_file(file_path, branch)
|
||||
|
||||
@@ -158,7 +158,7 @@ class Git::Gitlab::Client < Git::Client
|
||||
response = HTTParty.post(
|
||||
"#{gitlab_api_base}/projects/#{encoded_url}/merge_requests/#{pr_number}/notes",
|
||||
headers: { "Authorization" => "Bearer #{access_token}", "Content-Type" => "application/json" },
|
||||
body: { body: body }.to_json
|
||||
body: { body: "[canine] #{body}" }.to_json
|
||||
)
|
||||
raise "Failed to add comment: #{response.body}" unless response.success?
|
||||
|
||||
|
||||
@@ -16,12 +16,27 @@ RSpec.describe Git::Gitlab::Client do
|
||||
end
|
||||
|
||||
context 'when webhook already exists' do
|
||||
let(:webhook) { { 'id' => 123 } }
|
||||
|
||||
before do
|
||||
allow(client).to receive(:webhook_exists?).and_return(true)
|
||||
allow(client).to receive(:webhook).and_return(webhook)
|
||||
end
|
||||
|
||||
it 'returns early without creating webhook' do
|
||||
expect(HTTParty).not_to receive(:post)
|
||||
it 'updates the existing webhook' do
|
||||
expect(HTTParty).to receive(:put).with(
|
||||
"#{gitlab_api_base}/projects/#{client.encoded_url}/hooks/#{webhook['id']}",
|
||||
headers: { "Authorization" => "Bearer #{access_token}", "Content-Type" => "application/json" },
|
||||
body: {
|
||||
url: webhook_url,
|
||||
name: "canine-webhook",
|
||||
push_events: true,
|
||||
merge_requests_events: true,
|
||||
enable_ssl_verification: true,
|
||||
token: described_class::GITLAB_WEBHOOK_SECRET
|
||||
}.to_json
|
||||
).and_return(success_response)
|
||||
|
||||
client.register_webhook!
|
||||
end
|
||||
end
|
||||
@@ -39,6 +54,7 @@ RSpec.describe Git::Gitlab::Client do
|
||||
url: webhook_url,
|
||||
name: "canine-webhook",
|
||||
push_events: true,
|
||||
merge_requests_events: true,
|
||||
enable_ssl_verification: true,
|
||||
token: described_class::GITLAB_WEBHOOK_SECRET
|
||||
}.to_json
|
||||
|
||||
Reference in New Issue
Block a user