Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
242 changes: 242 additions & 0 deletions .github/workflows/sync-upstream.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
name: Sync upstream

on:
# TEMPORARY: testing on feature branch — remove before merging to cohere.
push:
branches:
- feat/sync-upstream-workflow

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Temporary push trigger left in workflow file

Medium Severity

The push trigger on branch feat/sync-upstream-workflow is annotated with a comment explicitly stating it's "TEMPORARY: testing on feature branch — remove before merging to cohere." This debug trigger is still present and will cause the full sync workflow (including pushes to main and PR creation) to run on every push to that feature branch, and it will remain active after merging unless removed.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5b75df5. Configure here.

schedule:
# Every Monday at 09:00 UTC
- cron: "0 9 * * 1"
workflow_dispatch:
inputs:
upstream_ref:
description: "Upstream ref to sync from (default: main)"
required: false
default: "main"
cohere_branch:
description: "Cohere branch to merge into"
required: false
default: "cohere"

# Deny all permissions at the workflow level; jobs opt in explicitly below.
permissions: {}

# Only one sync workflow runs at a time — prevents racing pushes to main or
# duplicate sync PRs if a manual dispatch overlaps the cron schedule.
concurrency:
group: sync-upstream
cancel-in-progress: false

env:
UPSTREAM_REPO: https://github.com/confidential-containers/cloud-api-adaptor.git
UPSTREAM_REF: ${{ inputs.upstream_ref || 'main' }}
COHERE_BRANCH: ${{ inputs.cohere_branch || 'cohere' }}

jobs:
# ── Step 1: fast-forward origin/main to match upstream/main ──────────────
sync-main:
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
name: Fast-forward main from upstream
runs-on: ubuntu-latest
permissions:
contents: write # push the fast-forwarded main branch
outputs:
new_commits: ${{ steps.ff.outputs.new_commits }}
upstream_sha: ${{ steps.ff.outputs.upstream_sha }}
# GH_TOKEN must be available to every step — `gh auth setup-git`
# registers `gh` as a git credential helper, and that helper shells
# out to `gh` at push-time, which reads $GH_TOKEN from the environment.
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Checkout main
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: main
fetch-depth: 0
# zizmor: token is set up explicitly below via `gh auth setup-git`
# so it isn't persisted in .git/config after this step.
persist-credentials: false

- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
gh auth setup-git

- name: Fast-forward main to upstream
id: ff
run: |
git remote add upstream "$UPSTREAM_REPO" || true
git fetch upstream "$UPSTREAM_REF"

BEHIND=$(git rev-list --count "HEAD..upstream/$UPSTREAM_REF")
UPSTREAM_SHA=$(git rev-parse --short "upstream/$UPSTREAM_REF")
echo "upstream_sha=$UPSTREAM_SHA" >> "$GITHUB_OUTPUT"

if [ "$BEHIND" -eq 0 ]; then
echo "main is already up to date with upstream."
echo "new_commits=0" >> "$GITHUB_OUTPUT"
exit 0
fi

AHEAD=$(git rev-list --count "upstream/$UPSTREAM_REF..HEAD")
if [ "$AHEAD" -ne 0 ]; then
echo "::error::origin/main is $AHEAD commits AHEAD of upstream — cannot fast-forward."
echo "::error::Remove the extra commits first (rebase or reset) before syncing."
exit 1
fi

git merge --ff-only "upstream/$UPSTREAM_REF"
git push origin main
echo "new_commits=$BEHIND" >> "$GITHUB_OUTPUT"
echo "Fast-forwarded main by $BEHIND commits to $UPSTREAM_SHA"

# ── Step 2: merge updated main into the cohere branch via PR ─────────────
sync-cohere:
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
name: Merge main into cohere via PR
needs: sync-main
runs-on: ubuntu-latest
permissions:
contents: write # push the sync/* branch
pull-requests: write # create the sync PR via `gh pr create`
# GH_TOKEN must be available to every step — `gh auth setup-git`
# registers `gh` as a git credential helper, and that helper shells
# out to `gh` at push-time, which reads $GH_TOKEN from the environment.
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Checkout cohere branch
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ env.COHERE_BRANCH }}
fetch-depth: 0
# zizmor: token is set up explicitly below via `gh auth setup-git`
# so it isn't persisted in .git/config after this step.
persist-credentials: false

- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
gh auth setup-git

- name: Check if cohere is behind main
id: check
run: |
git fetch origin main
BEHIND=$(git rev-list --count HEAD..origin/main)
echo "behind=$BEHIND" >> "$GITHUB_OUTPUT"
echo "Cohere branch is $BEHIND commits behind origin/main"

DATE=$(date +%Y-%m-%d)
SHORT_SHA=$(git rev-parse --short origin/main)
echo "sync_branch=sync/upstream-${DATE}-${SHORT_SHA}" >> "$GITHUB_OUTPUT"

- name: Skip if up to date
if: steps.check.outputs.behind == '0'
run: echo "Cohere branch is already up to date with main. Nothing to do."

- name: Create sync branch and check for conflicts
if: steps.check.outputs.behind != '0'
id: merge
env:
SYNC_BRANCH: ${{ steps.check.outputs.sync_branch }}
run: |
# The sync branch is created at origin/main so it's always ahead of
# cohere by $BEHIND commits. The PR merges this into cohere via the
# GitHub UI, which handles clean merges and surfaces conflicts
# natively — the merge commit is never pushed from CI.
# (If we instead tried to pre-merge in CI and aborted on conflict,
# the sync branch would equal cohere HEAD and `gh pr create` would
# fail with "No commits between cohere and <sync-branch>".)
git branch "$SYNC_BRANCH" origin/main

# Preflight merge — purely to report conflict status in the PR body.
# Never committed or pushed; aborted either way.
if git merge --no-commit --no-ff origin/main; then
echo "conflict=false" >> "$GITHUB_OUTPUT"
else
echo "conflict=true" >> "$GITHUB_OUTPUT"
echo ""
echo "=== CONFLICT: listing conflicted files ==="
git diff --name-only --diff-filter=U
fi
git merge --abort 2>/dev/null || true

- name: Push sync branch
if: steps.check.outputs.behind != '0'
env:
SYNC_BRANCH: ${{ steps.check.outputs.sync_branch }}
run: git push origin "$SYNC_BRANCH"

- name: Create pull request (clean merge)
if: steps.check.outputs.behind != '0' && steps.merge.outputs.conflict == 'false'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BEHIND: ${{ steps.check.outputs.behind }}
UPSTREAM_SHA: ${{ needs.sync-main.outputs.upstream_sha }}
SYNC_BRANCH: ${{ steps.check.outputs.sync_branch }}
run: |
gh pr create \
--base "$COHERE_BRANCH" \
--head "$SYNC_BRANCH" \
--title "Sync upstream ($UPSTREAM_SHA) — $BEHIND new commits" \
--body "$(cat <<EOF
## Upstream sync

Merges **${BEHIND}** new commits from \`main\` (synced from upstream) into \`${COHERE_BRANCH}\`.

**Upstream HEAD**: \`${UPSTREAM_SHA}\`
**Conflicts**: None — clean merge.

### Review checklist
- [ ] Scan the diff for changes that touch files we've customized
- [ ] Verify CI passes
- [ ] Check if any upstream changes obsolete our patches
EOF
)"

- name: Create pull request (conflicts)
if: steps.check.outputs.behind != '0' && steps.merge.outputs.conflict == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
UPSTREAM_SHA: ${{ needs.sync-main.outputs.upstream_sha }}
SYNC_BRANCH: ${{ steps.check.outputs.sync_branch }}
run: |
gh pr create \
--base "$COHERE_BRANCH" \
--head "$SYNC_BRANCH" \
--title "Sync upstream ($UPSTREAM_SHA) — needs conflict resolution" \
--body "$(cat <<EOF
## Upstream sync — manual merge needed

Upstream has new commits to merge into \`${COHERE_BRANCH}\`, but there are conflicts.

**Upstream HEAD**: \`${UPSTREAM_SHA}\`

### How to resolve

The sync branch already contains the upstream commits (it points at
\`origin/main\`). To make it mergeable into \`${COHERE_BRANCH}\`,
merge cohere into the sync branch and resolve conflicts there:

\`\`\`bash
git fetch origin
git checkout ${SYNC_BRANCH}
git merge origin/${COHERE_BRANCH}
# Git will show conflicts — resolve them in your IDE, then:
git add -A && git commit
git push origin ${SYNC_BRANCH}
\`\`\`

Your IDE will show the native merge conflict UI with accept-theirs /
accept-ours / accept-both options for each conflict. Once the push
succeeds, the PR will become mergeable.

### Review checklist
- [ ] Resolve all conflicts
- [ ] Verify CI passes
- [ ] Check if any upstream changes obsolete our patches
EOF
)"
Loading