Upstream Sync & Release #54
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Upstream Sync & Release | |
| on: | |
| schedule: | |
| - cron: '0 2 * * *' # Run at 2 AM UTC daily | |
| workflow_dispatch: | |
| jobs: | |
| sync_and_release: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| actions: write | |
| pull-requests: write | |
| steps: | |
| - name: Checkout Code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.PAT || secrets.GITHUB_TOKEN }} # Use PAT to trigger other workflows if provided | |
| - name: Configure Git | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "41898282+github-actions[bot]@users.noreply.github.com" | |
| - name: Add Upstream Remote | |
| run: git remote add upstream https://github.com/EchoMusicApp/Echo-Music.git || true | |
| - name: Fetch Upstream | |
| run: git fetch upstream --tags --force | |
| - name: Merge Upstream into Main | |
| run: | | |
| git config --global gc.auto 0 | |
| rm -f .git/index.lock | |
| git checkout main | |
| # We try to merge upstream/main without automatically committing | |
| git merge upstream/main -X ours --allow-unrelated-histories --no-commit || { | |
| echo "Merge conflicts detected (e.g. rename/delete). Resolving in favor of HEAD..." | |
| git diff --name-only --diff-filter=U | while read -r file; do | |
| if git rev-parse HEAD:"$file" >/dev/null 2>&1; then | |
| git checkout HEAD -- "$file" || true | |
| git add -- "$file" || true | |
| else | |
| git rm -rf -- "$file" || true | |
| fi | |
| done | |
| } | |
| # GitHub Actions token doesn't have permission to modify workflows. | |
| # We must completely revert any changes or additions to the workflows folder made by upstream! | |
| git rm -rf .github/workflows/ || true | |
| git checkout HEAD -- .github/workflows/ || true | |
| # Force take RELEASE_INFO.md from upstream for release notes | |
| git checkout upstream/main -- RELEASE_INFO.md || true | |
| # Extract version from tag (e.g., v5.2.4 -> 5.2.4) and update versionName in app/build.gradle.kts | |
| LATEST_TAG=$(git describe --tags --abbrev=0 upstream/main 2>/dev/null || echo "") | |
| if [ -n "$LATEST_TAG" ]; then | |
| VERSION_NUM=${LATEST_TAG#v} | |
| sed -i "s/versionName = \".*\"/versionName = \"$VERSION_NUM\"/" app/build.gradle.kts | |
| fi | |
| # Now commit the merge | |
| git commit --no-edit || true | |
| # Remove analytics if they were re-introduced | |
| sed -i '/firebase-crashlytics/d' app/build.gradle.kts | |
| sed -i '/firebase-analytics/d' app/build.gradle.kts | |
| sed -i '/google-services/d' build.gradle.kts | |
| sed -i '/firebase-crashlytics-gradle/d' build.gradle.kts | |
| # Force overwrite new author references | |
| python3 -c ' | |
| import os | |
| replacements = { | |
| "applicationId = \"iad1tya.echo.music\"": "applicationId = \"com.nullcore.music\"", | |
| "https://t.me/EchoMusicApp": "https://t.me/NullCoreDeveloper", | |
| "iad1tya.cyou": "NullCoreDeveloper", | |
| "https://instagram.com/iad1tya": "https://t.me/NullCoreDeveloper", | |
| "buymeacoffee.com/iad1tya": "github.com/NullCoreDeveloper", | |
| "patreon.com/cw/iad1tya": "t.me/NullCoreDeveloper", | |
| "iad1tya@upi": "nullcore@upi", | |
| "iad1tya/Echo-Music": "NullCoreDeveloper/NullMusic", | |
| "EchoMusicApp/Echo-Music": "NullCoreDeveloper/NullMusic", | |
| "Echo Music": "NullMusic", | |
| "echomusic": "nullmusic" | |
| } | |
| for root, dirs, files in os.walk("."): | |
| if ".git" in root or "build" in root or ".gradle" in root: | |
| continue | |
| for file in files: | |
| if file.endswith((".kt", ".md", ".json", ".xml", ".kts", ".properties")): | |
| path = os.path.join(root, file) | |
| try: | |
| with open(path, "r", encoding="utf-8") as f: content = f.read() | |
| new_content = content | |
| for old, new in replacements.items(): new_content = new_content.replace(old, new) | |
| if new_content != content: | |
| with open(path, "w", encoding="utf-8") as f: f.write(new_content) | |
| except Exception: pass | |
| ' | |
| # Rename the canvas module folder to match the string replacement above | |
| if [ -d "echomusiccanvas" ]; then | |
| git mv echomusiccanvas nullmusiccanvas || true | |
| fi | |
| git commit -am "chore: strip analytics and rewrite authorship from upstream changes" || true | |
| git push origin main | |
| - name: Sync Tags and Trigger Release | |
| run: | | |
| # Get latest tag from upstream | |
| LATEST_TAG=$(git describe --tags --abbrev=0 upstream/main 2>/dev/null || echo "") | |
| if [ -n "$LATEST_TAG" ]; then | |
| echo "Latest upstream tag is $LATEST_TAG" | |
| # Check if we already have this tag ON ORIGIN (our fork) | |
| if git ls-remote --tags origin | grep -q "refs/tags/$LATEST_TAG"; then | |
| echo "Tag $LATEST_TAG already exists on origin. No new release needed." | |
| else | |
| echo "New tag found! Creating and pushing tag $LATEST_TAG" | |
| # Delete the tag we just fetched from upstream so we can tag our local commit instead | |
| git tag -d $LATEST_TAG || true | |
| git tag $LATEST_TAG | |
| git push origin $LATEST_TAG | |
| echo "Pushed tag $LATEST_TAG to origin." | |
| # GITHUB_TOKEN pushes do not trigger other workflows automatically. | |
| # We explicitly trigger the build workflow using the gh CLI. | |
| echo "Triggering Android Build & Sign workflow for tag $LATEST_TAG..." | |
| env GH_TOKEN=${{ secrets.GITHUB_TOKEN }} gh workflow run gradle.yml --ref $LATEST_TAG || echo "Warning: Failed to trigger gradle.yml automatically." | |
| fi | |
| else | |
| echo "No tags found in upstream." | |
| fi |