Skip to content

Sync Upstream Releases #4

Sync Upstream Releases

Sync Upstream Releases #4

name: Sync Upstream Releases
on:
schedule:
- cron: '0 2 1 * *'
workflow_dispatch:
inputs:
force_sync:
description: 'Force sync all releases (ignore existing)'
required: false
default: 'false'
type: boolean
specific_tag:
description: 'Sync only specific tag (optional)'
required: false
type: string
env:
UPSTREAM_REPO: 'pioarduino/registry'
FORK_REPO: ${{ github.repository }}
jobs:
sync-releases:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout Fork
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup GitHub CLI
run: |
gh --version
echo "${{ secrets.GITHUB_TOKEN }}" | gh auth login --with-token
- name: Get Upstream Releases
id: upstream
run: |
echo "Fetching releases from $UPSTREAM_REPO..."
# Nur verfügbare Felder verwenden
gh release list -R "$UPSTREAM_REPO" \
--json tagName,name,isDraft,isPrerelease,publishedAt,createdAt \
--limit 50 > upstream_releases.json
echo "Found $(jq length upstream_releases.json) upstream releases"
cat upstream_releases.json | jq -r '.[].tagName' | head -10
- name: Get Fork Releases
id: fork
run: |
echo "Fetching existing releases from fork..."
gh release list -R "$FORK_REPO" \
--json tagName \
--limit 50 > fork_releases.json || echo "[]" > fork_releases.json
echo "Found $(jq length fork_releases.json) fork releases"
- name: Determine Releases to Sync
id: sync_plan
run: |
if [ "${{ github.event.inputs.specific_tag }}" != "" ]; then
echo "Syncing specific tag: ${{ github.event.inputs.specific_tag }}"
jq --arg tag "${{ github.event.inputs.specific_tag }}" \
'[.[] | select(.tagName == $tag)]' upstream_releases.json > releases_to_sync.json
elif [ "${{ github.event.inputs.force_sync }}" == "true" ]; then
echo "Force syncing all releases"
cp upstream_releases.json releases_to_sync.json
else
echo "Syncing new releases only"
jq --slurpfile fork fork_releases.json \
'[.[] | select(.tagName as $tag | $fork[0] | map(.tagName) | index($tag) | not)]' \
upstream_releases.json > releases_to_sync.json
fi
RELEASES_COUNT=$(jq length releases_to_sync.json)
echo "releases_count=$RELEASES_COUNT" >> $GITHUB_OUTPUT
echo "New releases to sync: $RELEASES_COUNT"
if [ "$RELEASES_COUNT" -gt 0 ]; then
echo "New releases to sync:"
jq -r '.[].tagName' releases_to_sync.json
fi
- name: Check for Asset Changes in Existing Releases
id: asset_changes
if: github.event.inputs.force_sync != 'true' && github.event.inputs.specific_tag == ''
run: |
echo "Checking for asset changes in existing releases..."
# Temporäre Datei für geänderte Releases
> changed_releases.txt
# Nur existierende Releases prüfen (die sowohl im upstream als auch im fork existieren)
jq --slurpfile upstream upstream_releases.json \
'[.[] | select(.tagName as $tag | $upstream[0] | map(.tagName) | index($tag))]' \
fork_releases.json > existing_releases.json
EXISTING_COUNT=$(jq length existing_releases.json)
echo "Checking $EXISTING_COUNT existing releases for asset changes..."
if [ "$EXISTING_COUNT" -gt 0 ]; then
jq -r '.[].tagName' existing_releases.json | while read -r TAG_NAME; do
echo "Checking assets for release: $TAG_NAME"
# Asset-Info vom upstream abrufen
UPSTREAM_ASSETS=$(gh release view "$TAG_NAME" -R "$UPSTREAM_REPO" --json assets --jq '.assets | sort_by(.name)' 2>/dev/null || echo "[]")
# Asset-Info vom fork abrufen
FORK_ASSETS=$(gh release view "$TAG_NAME" -R "$FORK_REPO" --json assets --jq '.assets | sort_by(.name)' 2>/dev/null || echo "[]")
# Asset-Signaturen vergleichen (Name + Größe)
UPSTREAM_SIG=$(echo "$UPSTREAM_ASSETS" | jq -r 'map("\(.name):\(.size // 0)") | sort | join(",")')
FORK_SIG=$(echo "$FORK_ASSETS" | jq -r 'map("\(.name):\(.size // 0)") | sort | join(",")')
if [ "$UPSTREAM_SIG" != "$FORK_SIG" ]; then
echo "Asset changes detected in: $TAG_NAME"
echo " Upstream assets: $UPSTREAM_SIG"
echo " Fork assets: $FORK_SIG"
echo "$TAG_NAME" >> changed_releases.txt
else
echo " No changes in: $TAG_NAME"
fi
done
fi
# Geänderte Releases zur Sync-Liste hinzufügen
if [ -s changed_releases.txt ]; then
echo ""
echo "Releases with asset changes:"
cat changed_releases.txt
# Geänderte Releases zur bestehenden Sync-Liste hinzufügen
while read -r tag; do
jq --arg tag "$tag" \
'. + [.[] | select(.tagName == $tag)]' \
upstream_releases.json >> temp_changed.json
done < changed_releases.txt
# Alle Releases kombinieren und Duplikate entfernen
if [ -f temp_changed.json ]; then
cat releases_to_sync.json temp_changed.json | jq -s 'add | unique_by(.tagName)' > combined_releases.json
mv combined_releases.json releases_to_sync.json
rm -f temp_changed.json
fi
CHANGED_COUNT=$(wc -l < changed_releases.txt)
echo "asset_changes_count=$CHANGED_COUNT" >> $GITHUB_OUTPUT
echo "Found $CHANGED_COUNT releases with asset changes"
else
echo "No asset changes detected in existing releases"
echo "asset_changes_count=0" >> $GITHUB_OUTPUT
fi
# Cleanup
rm -f changed_releases.txt existing_releases.json
# Update total count
TOTAL_COUNT=$(jq length releases_to_sync.json)
echo "total_releases_count=$TOTAL_COUNT" >> $GITHUB_OUTPUT
echo "Total releases to sync: $TOTAL_COUNT"
- name: Create Workspace
if: steps.sync_plan.outputs.releases_count > 0 || steps.asset_changes.outputs.asset_changes_count > 0
run: |
mkdir -p temp_downloads
- name: Sync Releases
if: steps.sync_plan.outputs.releases_count > 0 || steps.asset_changes.outputs.asset_changes_count > 0
run: |
TOTAL_RELEASES=$(jq length releases_to_sync.json)
echo "Processing $TOTAL_RELEASES releases..."
jq -c '.[]' releases_to_sync.json | while read -r release; do
TAG_NAME=$(echo "$release" | jq -r '.tagName')
RELEASE_NAME=$(echo "$release" | jq -r '.name')
IS_DRAFT=$(echo "$release" | jq -r '.isDraft')
IS_PRERELEASE=$(echo "$release" | jq -r '.isPrerelease')
echo "=== Syncing Release: $TAG_NAME ==="
# Release Notes separat abrufen (falls verfügbar)
RELEASE_BODY=""
if gh release view "$TAG_NAME" -R "$UPSTREAM_REPO" --json body >/dev/null 2>&1; then
RELEASE_BODY=$(gh release view "$TAG_NAME" -R "$UPSTREAM_REPO" --json body --jq '.body // ""')
fi
# Release-Flags setzen
DRAFT_FLAG=""
PRERELEASE_FLAG=""
[ "$IS_DRAFT" == "true" ] && DRAFT_FLAG="--draft"
[ "$IS_PRERELEASE" == "true" ] && PRERELEASE_FLAG="--prerelease"
# Existierendes Release löschen falls vorhanden
if gh release view "$TAG_NAME" -R "$FORK_REPO" >/dev/null 2>&1; then
echo "Release $TAG_NAME already exists, deleting for update..."
gh release delete "$TAG_NAME" -R "$FORK_REPO" --yes || true
sleep 2 # Kurze Pause nach dem Löschen
fi
# Release erstellen
echo "Creating release $TAG_NAME..."
if [ -n "$RELEASE_BODY" ]; then
echo "$RELEASE_BODY" > temp_body.md
gh release create "$TAG_NAME" \
-R "$FORK_REPO" \
--title "$RELEASE_NAME" \
--notes-file temp_body.md \
$DRAFT_FLAG $PRERELEASE_FLAG
else
gh release create "$TAG_NAME" \
-R "$FORK_REPO" \
--title "$RELEASE_NAME" \
--notes "Synced from upstream: $UPSTREAM_REPO" \
$DRAFT_FLAG $PRERELEASE_FLAG
fi
# Assets herunterladen und hochladen
echo "Processing assets for $TAG_NAME..."
cd temp_downloads
# Prüfen ob Assets existieren
ASSET_COUNT=$(gh release view "$TAG_NAME" -R "$UPSTREAM_REPO" --json assets --jq '.assets | length' 2>/dev/null || echo "0")
if [ "$ASSET_COUNT" -gt 0 ]; then
echo "Found $ASSET_COUNT assets, downloading..."
if gh release download "$TAG_NAME" -R "$UPSTREAM_REPO" 2>/dev/null; then
# Assets hochladen falls vorhanden
if ls ./* >/dev/null 2>&1; then
echo "Uploading assets to fork release..."
if gh release upload "$TAG_NAME" -R "$FORK_REPO" ./*; then
echo "Successfully uploaded all assets"
else
echo "Warning: Some assets failed to upload for $TAG_NAME"
fi
else
echo "No asset files found after download"
fi
else
echo "Warning: Failed to download assets for $TAG_NAME"
fi
# Cleanup downloaded files
rm -f ./* 2>/dev/null || true
else
echo "No assets found for $TAG_NAME"
fi
cd ..
echo "✅ Successfully synced release: $TAG_NAME"
echo ""
done
- name: Summary
if: always()
run: |
echo "=== Sync Summary ==="
echo "Upstream repo: $UPSTREAM_REPO"
echo "Fork repo: $FORK_REPO"
echo "New releases synced: ${{ steps.sync_plan.outputs.releases_count }}"
echo "Updated releases (asset changes): ${{ steps.asset_changes.outputs.asset_changes_count }}"
echo "Total releases processed: ${{ steps.asset_changes.outputs.total_releases_count }}"
echo ""
echo "Current fork releases (latest 10):"
gh release list -R "$FORK_REPO" --limit 10 || echo "No releases found"
- name: Cleanup
if: always()
run: |
rm -rf temp_downloads
rm -f upstream_releases.json fork_releases.json releases_to_sync.json temp_body.md