Skip to content

Commit

Permalink
rework sync public pr pipeline in use ruby and open PRs
Browse files Browse the repository at this point in the history
  • Loading branch information
catkins committed Sep 18, 2024
1 parent c8bdfa2 commit b2f3fea
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 15 deletions.
13 changes: 12 additions & 1 deletion .buildkite/pipeline.sync_public_pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,16 @@ steps:
text: "Pull Request Number"
format: "^[0-9]+$"

- command: "bin/sync-public-pr"
- label: ":git: Sync Public PR to Private Repo"
command: "bin/sync-public-pr"
depends_on: collect_pr_number
plugins:
- docker#v5.11.0:
image: "ruby:3.3-bookworm"
propagate-environment: true
mount-buildkite-agent: true
mount-ssh-agent: true
environment:
- GH_TOKEN
- GH_PRIVATE_REPO
- GH_PUBLIC_REPO
133 changes: 119 additions & 14 deletions bin/sync-public-pr
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)

0 comments on commit b2f3fea

Please sign in to comment.