Skip to content

Automation Patterns

Common patterns for running Copybara in CI/CD pipelines.

Sync immediately when source changes:

name: Sync on Push
on:
push:
branches: [main]
paths:
- "src/**"
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: java -jar copybara.jar migrate copy.bara.sky export --ignore-noop

Best for: Real-time synchronization

Sync on a schedule:

name: Scheduled Sync
on:
schedule:
- cron: "0 0 * * *" # Daily at midnight
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: java -jar copybara.jar migrate copy.bara.sky export --ignore-noop

Best for: Batching changes, reducing noise

On-demand synchronization:

name: Manual Sync
on:
workflow_dispatch:
inputs:
workflow:
description: "Workflow to run"
required: true
default: "export"
type: choice
options:
- export
- import
init_history:
description: "Initialize history (first-time sync)"
type: boolean
default: false
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: |
FLAGS="--ignore-noop"
if [ "${{ inputs.init_history }}" = "true" ]; then
FLAGS="--init-history"
fi
java -jar copybara.jar migrate copy.bara.sky ${{ inputs.workflow }} $FLAGS

Best for: Controlled deployments, initial setup

Sync when PRs are merged:

name: Sync on PR Merge
on:
pull_request:
types: [closed]
branches: [main]
jobs:
sync:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: java -jar copybara.jar migrate copy.bara.sky export --ignore-noop

Best for: Ensuring reviewed changes are synced

Validate before syncing:

name: Validate and Sync
on:
push:
branches: [main]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: java -jar copybara.jar validate copy.bara.sky export
sync:
needs: validate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: java -jar copybara.jar migrate copy.bara.sky export --ignore-noop

Best for: Catching config errors early

Sync multiple workflows in parallel:

name: Multi-Workflow Sync
on:
push:
branches: [main]
jobs:
sync:
runs-on: ubuntu-latest
strategy:
matrix:
workflow: [export-core, export-cli, export-docs]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: java -jar copybara.jar migrate copy.bara.sky ${{ matrix.workflow }} --ignore-noop

Best for: Monorepo extractions

Sync based on changed paths:

name: Conditional Sync
on:
push:
branches: [main]
jobs:
detect-changes:
runs-on: ubuntu-latest
outputs:
src: ${{ steps.filter.outputs.src }}
docs: ${{ steps.filter.outputs.docs }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: filter
with:
filters: |
src:
- 'src/**'
docs:
- 'docs/**'
sync-src:
needs: detect-changes
if: needs.detect-changes.outputs.src == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: java -jar copybara.jar migrate copy.bara.sky export-src --ignore-noop
sync-docs:
needs: detect-changes
if: needs.detect-changes.outputs.docs == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: java -jar copybara.jar migrate copy.bara.sky export-docs --ignore-noop

Best for: Selective syncing based on changes

Require approval before syncing:

name: Gated Sync
on:
push:
branches: [main]
jobs:
preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: |
java -jar copybara.jar migrate copy.bara.sky export \
--folder-destination /tmp/preview
- run: |
echo "## Preview" >> $GITHUB_STEP_SUMMARY
find /tmp/preview -type f | head -20 >> $GITHUB_STEP_SUMMARY
approve:
needs: preview
runs-on: ubuntu-latest
environment: production # Requires approval
steps:
- run: echo "Approved!"
sync:
needs: approve
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: java -jar copybara.jar migrate copy.bara.sky export --ignore-noop

Best for: High-risk syncs requiring human approval

Robust error handling:

- name: Run Copybara
id: copybara
continue-on-error: true
run: |
java -jar copybara.jar migrate copy.bara.sky export 2>&1 | tee copybara.log
exit ${PIPESTATUS[0]}
- name: Handle result
run: |
if [ "${{ steps.copybara.outcome }}" = "success" ]; then
echo "Sync completed successfully"
elif grep -q "NOOP" copybara.log; then
echo "No changes to sync - this is OK"
else
echo "Sync failed!"
cat copybara.log
exit 1
fi

Notify on sync status:

- name: Notify on failure
if: failure()
uses: slackapi/slack-github-action@v2
with:
webhook: ${{ secrets.SLACK_WEBHOOK }}
payload: |
{
"text": "Copybara sync failed: ${{ github.repository }}"
}

Prevent parallel syncs:

concurrency:
group: copybara-${{ github.workflow }}
cancel-in-progress: false # Don't cancel running syncs