Skip to content

GitHub Integration

Copybara has deep integration with GitHub for both reading and writing code, as well as interacting with the GitHub API.

Read from a GitHub repository with API integration:

origin = git.github_origin(
url = "https://github.com/org/repo",
ref = "main",
)
origin = git.github_origin(
url = "https://github.com/org/repo",
ref = "main",
review_state = "APPROVED",
review_approvers = ["maintainer1", "maintainer2"],
)

Read from GitHub pull requests:

origin = git.github_pr_origin(
url = "https://github.com/org/repo",
branch = "main",
required_labels = ["ready-to-merge"],
)

Push directly to a GitHub repository:

destination = git.github_destination(
url = "https://github.com/org/repo",
push = "main",
)

Create pull requests:

destination = git.github_pr_destination(
url = "https://github.com/org/repo",
destination_ref = "main",
pr_branch = "copybara/sync-${CONTEXT_REFERENCE}",
title = "Sync from internal",
body = "Automated sync",
)
destination = git.github_pr_destination(
url = "https://github.com/org/repo",
destination_ref = "main",
pr_branch = "copybara/sync-${CONTEXT_REFERENCE}",
title = "Sync from internal",
body = """\
## Summary
Automated sync from internal repository.
## Changes
See commit history for details.
## Checklist
- [ ] Review changes
- [ ] Run tests
- [ ] Approve and merge
""",
draft = False,
update_description = True,
assignees = ["reviewer1", "reviewer2"],
labels = ["automated", "documentation"],
)

Interact with GitHub API in feedback workflows:

destination = git.github_api(
url = "https://github.com/org/repo",
)

Listen to GitHub events:

origin = git.github_trigger(
url = "https://github.com/org/repo",
events = ["pull_request", "push"],
)

In feedback workflows, you can perform API actions:

def _my_action(ctx):
# Create an issue
ctx.destination.create_issue(
title = "Issue title",
body = "Issue body",
labels = ["bug"],
)
# Add a comment
ctx.destination.add_comment(
number = 123,
body = "Automated comment",
)
# Get PR info
pr = ctx.destination.get_pull_request(123)
return ctx.success()
  1. Go to GitHub Settings → Developer settings → Personal access tokens
  2. Generate new token (classic)
  3. Select scopes: repo, workflow (if needed)
  4. Copy token
  1. Go to GitHub Settings → Developer settings → Personal access tokens → Fine-grained tokens
  2. Generate new token
  3. Select repository access: Only specific repositories
  4. Select permissions:
    • Contents: Read and write
    • Pull requests: Read and write
    • Metadata: Read
Terminal window
# Add SSH key
ssh-add ~/.ssh/id_ed25519
# Use SSH URL in config
origin = git.origin(
url = "git@github.com:org/repo.git",
ref = "main",
)

Available in github_pr_destination:

VariableDescription
${CONTEXT_REFERENCE}Source commit SHA (short)
${COPYBARA_CONTEXT_REFERENCE}Same as above
pr_branch = "copybara/sync-${CONTEXT_REFERENCE}",
title = "Sync: ${CONTEXT_REFERENCE}",

When running multiple times:

ScenarioBehavior
PR doesn’t existCreate new PR
PR exists (open)Update branch (force push)
PR mergedCreate new PR
PR closedCreate new PR

GitHub API has rate limits:

  • Authenticated: 5,000 requests/hour
  • Search API: 30 requests/minute

Copybara handles rate limiting automatically with retries.

core.workflow(
name = "export",
origin = git.origin(url = internal_url, ref = "main"),
destination = git.github_destination(
url = github_url,
push = "main",
),
...
)
core.workflow(
name = "export-pr",
origin = git.origin(url = internal_url, ref = "main"),
destination = git.github_pr_destination(
url = github_url,
destination_ref = "main",
),
...
)
core.workflow(
name = "import",
origin = git.github_pr_origin(
url = github_url,
branch = "main",
required_labels = ["approved"],
),
destination = git.gerrit_destination(
url = internal_url,
push_to_refs_for = "main",
),
mode = "CHANGE_REQUEST_FROM_SOT",
...
)