-
Notifications
You must be signed in to change notification settings - Fork 249
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #16 from buildkite/catkins/open-pr-for-public-sync
Automatically Open PRs when syncing public to private sync
- Loading branch information
Showing
3 changed files
with
168 additions
and
30 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,129 @@ | ||
#!/usr/bin/env bash | ||
#!/usr/bin/env ruby | ||
|
||
set -euo pipefail | ||
require "net/http" | ||
require "open3" | ||
require "json" | ||
|
||
PR_NUMBER=$(buildkite-agent meta-data get "pull_request_number") | ||
TARGET_BRANCH="docs-public-pr-${PR_NUMBER}" | ||
SOURCE_REF="pull/${PR_NUMBER}/head" | ||
# Job params | ||
GH_TOKEN = ENV.fetch("GH_TOKEN") | ||
PUBLIC_GH_REPO = ENV.fetch("PUBLIC_GH_REPO") | ||
PRIVATE_GH_REPO = ENV.fetch("PRIVATE_GH_REPO") | ||
|
||
echo "+++ Syncing PR #${PR_NUMBER} to local branch ${TARGET_BRANCH}" | ||
PR_NUMBER = `buildkite-agent meta-data get "pull_request_number"`.strip.to_i | ||
TARGET_BRANCH = "docs-public-pr-#{PR_NUMBER}" | ||
|
||
set -x | ||
class GithubClient | ||
def initialize | ||
@client = Net::HTTP.new("api.github.com", 443) | ||
@client.use_ssl = true | ||
end | ||
|
||
git fetch "[email protected]:${PUBLIC_GH_REPO}.git" "${SOURCE_REF}:${TARGET_BRANCH}" | ||
def public_pr(pr_number) | ||
# https://docs.github.com/en/rest/pulls/pulls?apiVersion=2022-11-28#get-a-pull-request | ||
response = @client.get("/repos/#{PUBLIC_GH_REPO}/pulls/#{pr_number}", headers) | ||
puts response | ||
JSON.parse(response.body) | ||
end | ||
|
||
git push --force origin "${TARGET_BRANCH}" | ||
def private_pr_for_branch(branch_name) | ||
# https://docs.github.com/en/rest/pulls/pulls?apiVersion=2022-11-28#list-pull-requests | ||
# note this ignores closed/merged PRs | ||
response = @client.get("/repos/#{PRIVATE_GH_REPO}/pulls?head=buildkite:#{branch_name}", headers) | ||
puts response | ||
JSON.parse(response.body).first | ||
end | ||
|
||
CREATE_PR_LINK="https://github.com/${PRIVATE_GH_REPO}/compare/${TARGET_BRANCH}?expand=1" | ||
def open_pr(title:, body:, branch:) | ||
# https://docs.github.com/en/rest/pulls/pulls?apiVersion=2022-11-28#create-a-pull-request | ||
response = @client.post("/repos/#{PRIVATE_GH_REPO}/pulls", { | ||
title: title, | ||
body: body, | ||
head: branch, | ||
base: "main" | ||
}.to_json, headers) | ||
puts response | ||
JSON.parse(response.body) | ||
end | ||
|
||
ANNOTATION_CONTENT="Synced PR ${PUBLIC_GH_REPO}#${PR_NUMBER} to private repo branch \`${TARGET_BRANCH}\`. | ||
private | ||
|
||
Open PR: ${CREATE_PR_LINK} | ||
" | ||
def headers | ||
{ | ||
"Accept" => "application/vnd.github+json", | ||
"Authorization" => "Bearer #{GH_TOKEN}", | ||
"X-GitHub-Api-Version" =>"2022-11-28" | ||
} | ||
end | ||
end | ||
|
||
buildkite-agent annotate --context pr-link --style "info" "${ANNOTATION_CONTENT}" | ||
def write_annotation(content, style: "info") | ||
Open3.capture2("buildkite-agent", "annotate", "--style", style, stdin_data: content) | ||
end | ||
|
||
client = GithubClient.new | ||
|
||
puts "+++ :git: Syncing #{PUBLIC_GH_REPO} PR ##{PR_NUMBER} to local branch #{TARGET_BRANCH}" | ||
|
||
# pull the magic PR ref from the public repo into local docs-public-pr-<PR_NUMBER> branch | ||
source_ref = "pull/#{PR_NUMBER}/head" | ||
|
||
# https://git-scm.com/docs/git-fetch see docs on refspec format | ||
refspec = "#{source_ref}:#{TARGET_BRANCH}" | ||
|
||
`git fetch --force "[email protected]:#{PUBLIC_GH_REPO}.git" "#{refspec}"` | ||
|
||
|
||
puts "+++ :git: Pushing branch #{TARGET_BRANCH} to #{PRIVATE_GH_REPO}" | ||
|
||
`git push --force origin "#{TARGET_BRANCH}"` | ||
|
||
puts "+++ :github: Fetching original PR #{PUBLIC_GH_REPO} ##{PR_NUMBER}" | ||
|
||
public_pr = client.public_pr(PR_NUMBER) | ||
|
||
puts "--- :octocat: Checking for PR for #{TARGET_BRANCH} in #{PRIVATE_GH_REPO}" | ||
|
||
private_pr = client.private_pr_for_branch(TARGET_BRANCH) | ||
puts private_pr | ||
|
||
if private_pr | ||
annotation_content = <<~ANNOTATION | ||
:open-pr: Re-synced PR #{PUBLIC_GH_REPO} ##{PR_NUMBER} to private repo branch `#{TARGET_BRANCH}`. | ||
Original PR: https://github.com/#{PUBLIC_GH_REPO}/pull/#{PR_NUMBER} | ||
Private PR: #{private_pr["html_url"]} :robot_face: | ||
ANNOTATION | ||
|
||
write_annotation(annotation_content) | ||
exit 0 | ||
end | ||
|
||
puts "+++ :open-pr: Creating PR for #{TARGET_BRANCH} in #{PRIVATE_GH_REPO}" | ||
|
||
pr_description = <<-PR_DESCRIPTION | ||
:robot: Synced by #{ENV["BUILDKITE_BUILD_URL"]} :robot: | ||
_Note_: The original public PR will automatically close when this PR is merged. If there are additional changes to sync from the public PR, re-run the [Docs (Sync public PR)](https://buildkite.com/buildkite/docs-sync-public-pr) Pipeline. | ||
--- | ||
## [docs##{PR_NUMBER}](#{public_pr["html_url"]}): #{public_pr["title"]} | ||
Opened by @#{public_pr.dig("user", "login")} | ||
#{public_pr["body"]} | ||
PR_DESCRIPTION | ||
|
||
private_pr = client.open_pr(title: public_pr["title"], body: pr_description, branch: TARGET_BRANCH) | ||
|
||
annotation_content = <<~ANNOTATION | ||
:open-pr: Synced PR #{PUBLIC_GH_REPO} ##{PR_NUMBER} to private repo branch `#{TARGET_BRANCH}`. | ||
Original PR: #{public_pr["html_url"]} - #{public_pr["title"]} by @#{public_pr.dig("user", "login")} | ||
Private PR: #{private_pr["html_url"]} :robot_face: | ||
ANNOTATION | ||
|
||
write_annotation(annotation_content) |
This file contains 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