Skip to content

chore(cairo): bound openzeppelin_interfaces to the 2.x line (#733) #48

chore(cairo): bound openzeppelin_interfaces to the 2.x line (#733)

chore(cairo): bound openzeppelin_interfaces to the 2.x line (#733) #48

name: Speedrun Sync and Update
on:
pull_request:
types: [closed]
branches: [main]
push:
branches: [develop]
paths:
- '.tool-versions'
- '**/package.json'
- 'yarn.lock'
- '**/Scarb.toml'
- '**/Scarb.lock'
- 'README.md'
workflow_dispatch:
inputs:
source_ref:
description: 'Source ref of scaffold-stark-2 to sync from (branch, tag, or SHA)'
required: false
default: 'main'
type: string
permissions:
contents: read
jobs:
check_commit:
if: github.event_name != 'pull_request' || github.event.pull_request.merged == true
runs-on: ubuntu-latest
outputs:
SHOULD_RUN: ${{ steps.check_commit.outputs.SHOULD_RUN }}
SOURCE_REF: ${{ steps.source.outputs.SOURCE_REF }}
steps:
- name: Checkout Files
uses: actions/checkout@v4
with:
token: ${{ secrets.ORG_GITHUB_TOKEN }}
- name: check if skip ci
id: check_commit
run: |
COMMIT_MESSAGE=$(git log -1 --pretty=%B)
if [[ "$COMMIT_MESSAGE" == *"[skip ci]"* ]]; then
echo "SHOULD_RUN=false" >> "$GITHUB_OUTPUT"
else
echo "SHOULD_RUN=true" >> "$GITHUB_OUTPUT"
fi
- name: Resolve source ref
id: source
run: |
case "${{ github.event_name }}" in
workflow_dispatch)
REF="${{ inputs.source_ref }}"
;;
push)
REF="${{ github.ref_name }}"
;;
*)
REF="main"
;;
esac
echo "SOURCE_REF=$REF" >> "$GITHUB_OUTPUT"
echo "Resolved source ref: $REF"
sync-speedrun:
needs: check_commit
if: ${{ needs.check_commit.outputs.SHOULD_RUN != 'false' }}
runs-on: ubuntu-22.04
steps:
- name: Checkout Source Repository
uses: actions/checkout@v4
with:
repository: Scaffold-Stark/scaffold-stark-2
ref: ${{ needs.check_commit.outputs.SOURCE_REF }}
token: ${{ secrets.ORG_GITHUB_TOKEN }}
path: source_repo
- name: Checkout Destination Repository
uses: actions/checkout@v4
with:
repository: Scaffold-Stark/speedrunstark
token: ${{ secrets.ORG_GITHUB_TOKEN }}
path: speedrun_repo
fetch-depth: 0
- name: Setup Git
run: |
git config --global user.name 'github-actions[bot]'
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
- name: Sync to temp branch
id: sync
env:
SOURCE_REF: ${{ needs.check_commit.outputs.SOURCE_REF }}
run: |
set -e
cd speedrun_repo
SHORT_SHA=$(cd ../source_repo && git rev-parse --short HEAD)
SOURCE_SHA=$(cd ../source_repo && git rev-parse HEAD)
SAFE_REF=$(echo "$SOURCE_REF" | tr '/' '-')
TEMP_BRANCH="sync/from-${SAFE_REF}-${SHORT_SHA}"
git fetch origin base-challenge-template
git checkout -B "$TEMP_BRANCH" origin/base-challenge-template
# Copy filter rules from source repo
cp ../source_repo/.github/sync-speedrun-filter-rules /tmp/sync-filter-rules
rsync -av --delete \
--exclude='.git/' \
--exclude='.claude/' \
--filter='merge /tmp/sync-filter-rules' \
--include='.github/' \
--include='.github/workflows/' \
--include='.github/workflows/main.yml' \
--include='.github/sync-speedrun-filter-rules' \
--exclude='.github/*' \
--exclude='.github/workflows/*' \
../source_repo/ ./
# Sync the Compatible versions section from README.md.
# Failure here is the conflict trigger for this workflow.
cat > /tmp/sync-readme.py <<'PYEOF'
import re, sys
with open('../source_repo/README.md', 'r') as f:
source = f.read()
with open('README.md', 'r') as f:
dest = f.read()
source_match = re.search(r'## Compatible versions\s*\n(.*?)(?=\n##|\Z)', source, re.DOTALL)
if not source_match:
print('Could not find Compatible versions in source README', file=sys.stderr)
sys.exit(1)
versions_list = source_match.group(1).strip()
dest_pattern = r'(### Compatible versions\s*\n)(.*?)(?=\n###|\Z)'
dest_match = re.search(dest_pattern, dest, re.DOTALL)
if not dest_match:
print('Could not find Compatible versions in destination README', file=sys.stderr)
sys.exit(1)
old_content = dest_match.group(2)
requirements_link = ''
if 'Make sure you have the compatible versions' in old_content:
req_match = re.search(r'(Make sure you have.*?)(?=\n###|\Z)', old_content, re.DOTALL)
if req_match:
requirements_link = '\n\n' + req_match.group(1).strip()
new_section = dest_match.group(1) + versions_list + requirements_link
new_dest = re.sub(dest_pattern, new_section, dest, flags=re.DOTALL)
with open('README.md', 'w') as f:
f.write(new_dest)
print('Updated Compatible versions section')
PYEOF
CONFLICT=false
README_LOG=$(python3 /tmp/sync-readme.py 2>&1) || CONFLICT=true
if [ "$CONFLICT" = "true" ]; then
echo "::warning::README Compatible-versions rewrite failed; staging rsync changes for manual review."
echo "$README_LOG"
else
echo "$README_LOG"
fi
if [ -n "$(git status --porcelain)" ]; then
git add -A
git commit -m "chore: sync files from scaffold-stark-2 and update Compatible versions section (${SOURCE_REF} @ ${SHORT_SHA})"
git push --force-with-lease origin "$TEMP_BRANCH"
NOOP=false
else
echo "No changes to sync; destination already at parity."
NOOP=true
fi
{
echo "TEMP_BRANCH=$TEMP_BRANCH"
echo "SOURCE_SHA=$SOURCE_SHA"
echo "SHORT_SHA=$SHORT_SHA"
echo "CONFLICT=$CONFLICT"
echo "NOOP=$NOOP"
echo 'README_LOG<<README_LOG_EOF'
echo "${README_LOG:-Applied cleanly.}"
echo 'README_LOG_EOF'
} >> "$GITHUB_OUTPUT"
- name: Finalize sync (fast-forward or open PR)
id: finalize
if: steps.sync.outputs.NOOP != 'true'
env:
GH_TOKEN: ${{ secrets.ORG_GITHUB_TOKEN }}
DEST_REPO: Scaffold-Stark/speedrunstark
PROD_BRANCH: base-challenge-template
TEMP_BRANCH: ${{ steps.sync.outputs.TEMP_BRANCH }}
SOURCE_SHA: ${{ steps.sync.outputs.SOURCE_SHA }}
SHORT_SHA: ${{ steps.sync.outputs.SHORT_SHA }}
SOURCE_REF: ${{ needs.check_commit.outputs.SOURCE_REF }}
README_LOG: ${{ steps.sync.outputs.README_LOG }}
CONFLICT: ${{ steps.sync.outputs.CONFLICT }}
EVENT_NAME: ${{ github.event_name }}
run: |
set -e
cd speedrun_repo
if [ "$CONFLICT" = "true" ]; then
gh label create sync-conflict --color b60205 \
--description "Sync from scaffold-stark-2 hit a conflict needing manual resolution" \
--force --repo "$DEST_REPO"
gh label create needs-review --color fbca04 \
--description "Awaiting human review" \
--force --repo "$DEST_REPO"
BODY_FILE=$(mktemp)
{
echo "## Automated sync conflict from scaffold-stark-2"
echo
echo "The sync workflow could not rewrite the README \`Compatible versions\` section cleanly onto \`$PROD_BRANCH\`. The rsync portion of the sync has been committed to this branch so the README rewrite can be inspected against the latest tree."
echo
echo "| Field | Value |"
echo "| --- | --- |"
echo "| Source ref | \`$SOURCE_REF\` |"
echo "| Source SHA | \`$SOURCE_SHA\` |"
echo "| Trigger | \`$EVENT_NAME\` |"
echo "| Failing step | README \`Compatible versions\` rewriter |"
echo
echo "### Rewriter log"
echo
echo '```'
echo "$README_LOG"
echo '```'
echo
echo "### Manual resolution"
echo
echo "1. \`git fetch origin && git checkout $TEMP_BRANCH\`"
echo "2. Hand-edit \`README.md\` so the \`### Compatible versions\` section matches scaffold-stark-2's \`## Compatible versions\` block (preserve any \`Make sure you have the compatible versions\` link below it)."
echo "3. Commit, force-push the branch."
echo "4. When CI is green, merge this PR into \`$PROD_BRANCH\`."
} > "$BODY_FILE"
EXISTING=$(gh pr list --repo "$DEST_REPO" --head "$TEMP_BRANCH" --base "$PROD_BRANCH" --state open --json number --jq '.[0].number // empty')
if [ -n "$EXISTING" ]; then
gh pr edit "$EXISTING" --repo "$DEST_REPO" --body-file "$BODY_FILE"
echo "Updated existing conflict PR #$EXISTING"
else
gh pr create --repo "$DEST_REPO" \
--base "$PROD_BRANCH" \
--head "$TEMP_BRANCH" \
--title "Sync conflict from ${SOURCE_REF}@${SHORT_SHA}" \
--label sync-conflict \
--label needs-review \
--body-file "$BODY_FILE"
fi
rm -f "$BODY_FILE"
echo "OUTCOME=pr_opened" >> "$GITHUB_OUTPUT"
else
git fetch origin "$PROD_BRANCH" "$TEMP_BRANCH"
git checkout "$PROD_BRANCH"
git merge --ff-only "origin/$TEMP_BRANCH"
git push origin "$PROD_BRANCH"
git push origin --delete "$TEMP_BRANCH"
echo "OUTCOME=fast_forwarded" >> "$GITHUB_OUTPUT"
fi
- name: Notify Slack on fast-forward sync
if: success() && steps.finalize.outputs.OUTCOME == 'fast_forwarded'
uses: slackapi/slack-github-action@v1.26.0
with:
channel-id: ${{ secrets.SLACK_CHANNEL_ID }}
slack-message: "Successfully synced scaffold-stark-2 (${{ needs.check_commit.outputs.SOURCE_REF }}@${{ steps.sync.outputs.SHORT_SHA }}) to speedrunstark base-challenge-template."
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
- name: Notify Slack on conflict PR opened
if: success() && steps.finalize.outputs.OUTCOME == 'pr_opened'
uses: slackapi/slack-github-action@v1.26.0
with:
channel-id: ${{ secrets.SLACK_CHANNEL_ID }}
slack-message: "speedrunstark sync from ${{ needs.check_commit.outputs.SOURCE_REF }}@${{ steps.sync.outputs.SHORT_SHA }} hit a README rewrite conflict. Opened PR for manual review on branch ${{ steps.sync.outputs.TEMP_BRANCH }}."
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
- name: Notify Slack on no-op sync
if: success() && steps.sync.outputs.NOOP == 'true'
uses: slackapi/slack-github-action@v1.26.0
with:
channel-id: ${{ secrets.SLACK_CHANNEL_ID }}
slack-message: "speedrunstark sync from ${{ needs.check_commit.outputs.SOURCE_REF }}@${{ steps.sync.outputs.SHORT_SHA }}: no changes to apply."
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
- name: Notify Slack on Failure
if: failure()
uses: slackapi/slack-github-action@v1.26.0
with:
channel-id: ${{ secrets.SLACK_CHANNEL_ID }}
slack-message: "Failed to sync scaffold-stark-2 changes to speedrunstark repository (workflow error, not a README conflict)."
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}