Skip to content
This repository was archived by the owner on Apr 7, 2026. It is now read-only.

Upstream Sync

Upstream Sync #47

Workflow file for this run

name: Upstream Sync
on:
schedule:
# Daily at 06:00 UTC
- cron: "0 6 * * *"
workflow_dispatch:
inputs:
mode:
description: "Sync mode"
required: true
default: "pr"
type: choice
options:
- pr
- push
- dry-run
- scan-only
jobs:
sync:
runs-on: self-hosted
timeout-minutes: 60
steps:
- name: Checkout (full history for rebase)
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GH_PAT }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
# Nuke stale credential helpers on self-hosted runner (prevents "denied to TSavo")
git config --local --unset-all credential.helper 2>/dev/null || true
git config --global --unset-all credential.helper 2>/dev/null || true
- name: Clean working tree (self-hosted runner may have leftovers)
run: |
git checkout master 2>/dev/null || true
git rebase --abort 2>/dev/null || true
git reset --hard HEAD
git clean -fd
- name: Add upstream remote
run: |
git remote get-url upstream 2>/dev/null || \
git remote add upstream https://github.com/paperclipai/paperclip.git
git fetch upstream
- name: Install Agent SDK
run: |
rm -rf "$(npm root -g)/@anthropic-ai/.claude-code-"* "$(npm root -g)/@anthropic-ai/.claude-agent-sdk-"* 2>/dev/null || true
npm install -g @anthropic-ai/claude-code || npm install -g @anthropic-ai/claude-code
npm install -g @anthropic-ai/claude-agent-sdk || npm install -g @anthropic-ai/claude-agent-sdk
node -e "require('@anthropic-ai/claude-agent-sdk')" 2>/dev/null || echo "SDK import check: will resolve at runtime via global root"
- name: Write Claude credentials
run: |
mkdir -p ~/.claude
echo '${{ secrets.CLAUDE_CREDENTIALS_JSON }}' > ~/.claude/.credentials.json
- name: Check for upstream changes
id: check
run: |
BEHIND=$(git rev-list HEAD..upstream/master --count)
echo "behind=$BEHIND" >> "$GITHUB_OUTPUT"
if [ "$BEHIND" -eq 0 ]; then
echo "Up to date with upstream. Skipping sync."
else
echo "Behind upstream by $BEHIND commits."
fi
- name: Run upstream sync
if: steps.check.outputs.behind != '0' || contains(fromJSON('["scan-only", "dry-run"]'), github.event.inputs.mode)
env:
CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
GH_TOKEN: ${{ secrets.GH_PAT }}
run: |
MODE="${{ github.event.inputs.mode || 'pr' }}"
case "$MODE" in
push) FLAG="--push" ;;
pr) FLAG="--pr" ;;
dry-run) FLAG="--dry-run" ;;
scan-only) FLAG="--scan-only --dry-run" ;;
esac
node scripts/upstream-sync.mjs $FLAG
- name: Upload agent event log
if: always()
uses: actions/upload-artifact@v4
with:
name: agent-events-log
path: agent-events.log
if-no-files-found: ignore
retention-days: 14