isInitialRun #6
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: Multi-Platform-Build | |
| on: | |
| push: | |
| branches: [ main, master ] | |
| workflow_dispatch: | |
| inputs: | |
| use_ai: | |
| description: 'KI Analyse aktivieren?' | |
| required: true | |
| default: 'true' | |
| type: boolean | |
| permissions: | |
| contents: write # WICHTIG: Erlaubt dem Bot, Releases zu erstellen & README zu pushen | |
| env: | |
| # HIER DAS ZIEL-REPO FÜR RELEASES ANPASSEN | |
| # Leer lassen, um das aktuelle Repo zu verwenden | |
| RELEASE_OWNER: '' # z.B. pono1012 | |
| RELEASE_REPO: '' # z.B. techana | |
| jobs: | |
| # --- JOB 1: KI ANALYSE --- | |
| analyze_changes: | |
| name: 🧠 AI Analysis | |
| runs-on: ubuntu-latest | |
| outputs: | |
| full_notes: ${{ steps.generate_notes.outputs.full_notes || '⚠️ KI-Analyse momentan nicht verfügbar.' }} | |
| summary: ${{ steps.generate_notes.outputs.summary || 'Update' }} | |
| run_status: ${{ steps.generate_notes.outputs.run_status || 'skipped' }} | |
| update_type: ${{ steps.generate_notes.outputs.update_type || 'patch' }} | |
| install_text: ${{ steps.read_install.outputs.content }} | |
| steps: | |
| - uses: actions/checkout@v3 | |
| with: | |
| fetch-depth: 0 # Wichtig für die KI-Historie | |
| - name: Setup Node | |
| uses: actions/setup-node@v3 | |
| with: | |
| node-version: '16' | |
| # Lädt die Installationsanleitung in eine Variable | |
| - name: 📄 Read Install Template | |
| id: read_install | |
| run: | | |
| # Prüfen ob Datei existiert, sonst Fallback | |
| if [ -f .github/templates/INSTALLATION.md ]; then | |
| content=$(cat .github/templates/INSTALLATION.md) | |
| else | |
| content="Installation instructions not found." | |
| fi | |
| echo "content<<EOF" >> $GITHUB_OUTPUT | |
| echo "$content" >> $GITHUB_OUTPUT | |
| echo "EOF" >> $GITHUB_OUTPUT | |
| - name: 🧠 Generate Notes (Gemini) | |
| id: generate_notes | |
| continue-on-error: true | |
| uses: actions/github-script@v6 | |
| env: | |
| GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }} | |
| USE_AI: ${{ github.event_name == 'push' && 'true' || inputs.use_ai }} | |
| with: | |
| script: | | |
| const script = require('./.github/scripts/generate_notes.js') | |
| await script({github, context, core}) | |
| # Changelog und Status aktualisieren (nur wenn KI lief) | |
| - name: 📝 Update Changelog & State | |
| if: steps.generate_notes.outputs.run_status == 'success' | |
| env: | |
| FULL_NOTES: ${{ steps.generate_notes.outputs.full_notes }} | |
| UPDATE_TYPE: ${{ steps.generate_notes.outputs.update_type }} | |
| run: | | |
| # Wenn CHANGELOG.md noch nicht existiert, erstellen | |
| touch CHANGELOG.md | |
| DATE=$(date +'%Y-%m-%d') | |
| # LOGIK: Release = Neuer Eintrag oben. Patch = Unten anhängen. | |
| if [ "$UPDATE_TYPE" == "patch" ]; then | |
| # PATCH: Wir hängen den neuen Punkt einfach an die Datei an (oder unter den letzten Header) | |
| # Da wir es einfach halten wollen: Wir fügen eine Trennlinie ein, falls noch keine da ist, oder hängen direkt an. | |
| # Prüfen ob "### Patches" schon existiert im letzten Block? | |
| # Einfachste Lösung: Einfach unten an CHANGELOG.md anhängen. | |
| # Aber wir wollen es sauber. Wir fügen es oben unter den aktuellen Eintrag ein? | |
| # Nein, User wollte "einfach unten dran hängen". | |
| echo "" >> CHANGELOG.md | |
| echo "$FULL_NOTES" >> CHANGELOG.md | |
| else | |
| # RELEASE: Neuer Eintrag ganz oben | |
| { | |
| echo "### $DATE - Update" | |
| echo "" | |
| echo "$FULL_NOTES" | |
| echo "" | |
| echo "---" | |
| echo "" | |
| } > new_entry.md | |
| cat new_entry.md CHANGELOG.md > CHANGELOG.tmp && mv CHANGELOG.tmp CHANGELOG.md | |
| rm new_entry.md | |
| fi | |
| # State File committen (wird im nächsten Job gepusht oder hier) | |
| git config --global user.name "TechAna Bot" | |
| git config --global user.email "bot@techana.app" | |
| # WICHTIG: Auch die Patch-Notes Datei adden | |
| git add CHANGELOG.md .github/ai_state.json .github/current_patch_notes.md | |
| git commit -m "docs: Update Changelog & AI State [skip ci]" || echo "No changes" | |
| git push | |
| # --- JOB 2: BUILD & RELEASE (Shorebird) --- | |
| build: | |
| needs: analyze_changes | |
| name: 🚀 Build ${{ matrix.platform }} | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - platform: android | |
| os: ubuntu-latest | |
| artifact-path: TechAna-android.apk | |
| - platform: ios | |
| os: macos-latest | |
| artifact-path: TechAna-iOS.ipa | |
| - platform: windows | |
| os: windows-latest | |
| artifact-path: TechAna-windows.zip | |
| - platform: macos | |
| os: macos-latest | |
| artifact-path: TechAna-macos.zip | |
| - platform: linux | |
| os: ubuntu-latest | |
| artifact-path: TechAna-linux.zip | |
| steps: | |
| - uses: actions/checkout@v3 | |
| - name: 🐦 Setup Shorebird | |
| uses: shorebirdtech/setup-shorebird@v1 | |
| with: | |
| cache: true | |
| - name: Get Version | |
| id: get_version | |
| run: echo "VERSION=$(grep 'version:' pubspec.yaml | cut -d ' ' -f 2)" >> $GITHUB_ENV | |
| shell: bash | |
| # Linux Dependencies | |
| - name: Install Linux dependencies | |
| if: matrix.platform == 'linux' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev liblzma-dev \ | |
| libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev zip \ | |
| libsecret-1-dev libjsoncpp-dev libnotify-dev | |
| - uses: subosito/flutter-action@v2 | |
| with: | |
| channel: 'stable' | |
| cache: true | |
| - run: flutter pub get | |
| - run: flutter clean | |
| # --- SHOREBIRD BUILD LOGIK --- | |
| - name: 🏗 Build Platform via Shorebird | |
| id: shorebird_build | |
| env: | |
| SHOREBIRD_TOKEN: ${{ secrets.SHOREBIRD_TOKEN }} | |
| run: | | |
| echo "SHOULD_UPLOAD=false" >> $GITHUB_ENV | |
| echo "🚀 Starting Shorebird logic for ${{ matrix.platform }}..." | |
| # Android | |
| if [ "${{ matrix.platform }}" == "android" ]; then | |
| if shorebird patch android --no-confirm --release-version=${{ env.VERSION }}; then | |
| echo "✅ Patch successfully." | |
| else | |
| shorebird release android --artifact=apk --no-confirm | |
| echo "SHOULD_UPLOAD=true" >> $GITHUB_ENV | |
| fi | |
| # iOS | |
| elif [ "${{ matrix.platform }}" == "ios" ]; then | |
| if shorebird patch ios --no-codesign --no-confirm --release-version=${{ env.VERSION }}; then | |
| echo "✅ Patch successfully." | |
| else | |
| shorebird release ios --no-codesign --no-confirm | |
| echo "SHOULD_UPLOAD=true" >> $GITHUB_ENV | |
| fi | |
| # Windows | |
| elif [ "${{ matrix.platform }}" == "windows" ]; then | |
| if shorebird patch windows --no-confirm --release-version=${{ env.VERSION }}; then | |
| echo "✅ Patch successfully." | |
| else | |
| shorebird release windows --no-confirm | |
| echo "SHOULD_UPLOAD=true" >> $GITHUB_ENV | |
| fi | |
| # macOS | |
| elif [ "${{ matrix.platform }}" == "macos" ]; then | |
| if shorebird patch macos --no-confirm --release-version=${{ env.VERSION }}; then | |
| echo "✅ Patch successfully." | |
| else | |
| shorebird release macos --no-confirm | |
| echo "SHOULD_UPLOAD=true" >> $GITHUB_ENV | |
| fi | |
| # Linux | |
| elif [ "${{ matrix.platform }}" == "linux" ]; then | |
| if shorebird patch linux --no-confirm --release-version=${{ env.VERSION }}; then | |
| echo "✅ Patch successfully." | |
| else | |
| shorebird release linux --no-confirm | |
| echo "SHOULD_UPLOAD=true" >> $GITHUB_ENV | |
| fi | |
| fi | |
| shell: bash | |
| # --- PACKAGING --- | |
| - name: 📦 Prepare Artifacts | |
| if: env.SHOULD_UPLOAD == 'true' | |
| run: | | |
| if [ "${{ matrix.platform }}" == "android" ]; then | |
| cp build/app/outputs/apk/release/app-release.apk ./TechAna-android.apk | |
| elif [ "${{ matrix.platform }}" == "ios" ]; then | |
| cd build/ios/archive/Runner.xcarchive/Products/Applications/ | |
| mkdir Payload && cp -r Runner.app Payload/ | |
| zip -qq -r TechAna-iOS.ipa Payload && mv TechAna-iOS.ipa $GITHUB_WORKSPACE/ | |
| elif [ "${{ matrix.platform }}" == "windows" ]; then | |
| powershell -Command "Compress-Archive -Path build/windows/x64/runner/Release/* -DestinationPath TechAna-windows.zip" | |
| elif [ "${{ matrix.platform }}" == "macos" ]; then | |
| cd build/macos/Build/Products/Release/ && zip -qq -r TechAna-macos.zip *.app && mv TechAna-macos.zip $GITHUB_WORKSPACE/ | |
| elif [ "${{ matrix.platform }}" == "linux" ]; then | |
| cd build/linux/x64/release/bundle/ | |
| zip -r TechAna-linux.zip . | |
| mv TechAna-linux.zip $GITHUB_WORKSPACE/ | |
| fi | |
| shell: bash | |
| - name: 📄 Create Version JSON | |
| if: matrix.platform == 'linux' && env.SHOULD_UPLOAD == 'true' | |
| run: | | |
| echo '{ "version": "${{ env.VERSION }}", "release_notes": "Update verfügbar" }' > version.json | |
| shell: bash | |
| - name: 📝 Prepare Upload Files | |
| if: env.SHOULD_UPLOAD == 'true' | |
| run: | | |
| echo "FILES_TO_UPLOAD<<EOF" >> $GITHUB_ENV | |
| if [ "${{ matrix.platform }}" == "android" ]; then echo "TechAna-android.apk" >> $GITHUB_ENV; fi | |
| if [ "${{ matrix.platform }}" == "ios" ]; then echo "TechAna-iOS.ipa" >> $GITHUB_ENV; fi | |
| if [ "${{ matrix.platform }}" == "windows" ]; then echo "TechAna-windows.zip" >> $GITHUB_ENV; fi | |
| if [ "${{ matrix.platform }}" == "macos" ]; then echo "TechAna-macos.zip" >> $GITHUB_ENV; fi | |
| if [ "${{ matrix.platform }}" == "linux" ]; then | |
| echo '{TechAna-linux.zip,version.json}' >> $GITHUB_ENV | |
| fi | |
| echo "EOF" >> $GITHUB_ENV | |
| shell: bash | |
| - name: 📤 Upload to Release | |
| if: env.SHOULD_UPLOAD == 'true' | |
| uses: svenstaro/upload-release-action@v2 | |
| with: | |
| repo_token: ${{ secrets.GITHUB_TOKEN }} | |
| file: ${{ env.FILES_TO_UPLOAD }} | |
| tag: v${{ env.VERSION }} | |
| overwrite: true | |
| file_glob: true | |
| body: | | |
| ## 🚀 TechAna v${{ env.VERSION }} | |
| ### 🤖 AI Update Report | |
| ${{ needs.analyze_changes.outputs.full_notes }} | |
| --- | |
| ${{ needs.analyze_changes.outputs.install_text }} | |
| # --- JOB 3: UPDATE RELEASE ON PATCH --- | |
| update_release_on_patch: | |
| name: 📝 Update Release on Patch | |
| needs: [analyze_changes, build] | |
| if: success() && needs.analyze_changes.outputs.update_type == 'patch' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v3 # Lädt den Code-Stand, der den Workflow gestartet hat | |
| - name: 🔄 Sync with remote changes from analysis job | |
| run: git pull origin ${{ github.ref_name }} | |
| shell: bash | |
| - name: 📄 Read Patch Notes | |
| id: read_patch_notes | |
| run: | | |
| if [ -f .github/current_patch_notes.md ]; then | |
| content=$(cat .github/current_patch_notes.md) | |
| else | |
| content="Keine Patch-Notes gefunden." | |
| fi | |
| echo "content<<EOF" >> $GITHUB_OUTPUT | |
| echo "$content" >> $GITHUB_OUTPUT | |
| echo "EOF" >> $GITHUB_OUTPUT | |
| - name: 🚀 Update Latest Release Body | |
| uses: actions/github-script@v6 | |
| env: | |
| PATCH_NOTES: ${{ steps.read_patch_notes.outputs.content }} | |
| INSTALL_NOTES: ${{ needs.analyze_changes.outputs.install_text }} | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const owner = process.env.RELEASE_OWNER || context.repo.owner; | |
| const repo = process.env.RELEASE_REPO || context.repo.repo; | |
| // 1. Get the latest release | |
| const { data: latestRelease } = await github.rest.repos.getLatestRelease({ | |
| owner, | |
| repo, | |
| }); | |
| if (!latestRelease) { | |
| core.setFailed("Kein Release gefunden zum Aktualisieren."); | |
| return; | |
| } | |
| console.log(`Aktualisiere Release: ${latestRelease.name} (ID: ${latestRelease.id})`); | |
| // 2. Lade die neuen und alten Inhalte | |
| const patchNotes = process.env.PATCH_NOTES; | |
| const installNotes = process.env.INSTALL_NOTES; | |
| const originalBody = latestRelease.body; | |
| // 3. Zerlege den Body in seine Teile: Basis-Notes, alte Patches, Installation | |
| const separator = "---"; | |
| const installHeader = "### 🛠 Installation & Downloads"; | |
| const patchHeader = "### 🩹 Patch vom"; | |
| // Finde die Installations-Sektion. Alles danach wird ignoriert. | |
| const installSectionIndex = originalBody.indexOf(installHeader); | |
| const topPart = installSectionIndex !== -1 ? originalBody.substring(0, installSectionIndex).trim() : originalBody.trim(); | |
| // Entferne den Separator am Ende des oberen Teils, falls vorhanden | |
| const cleanTopPart = topPart.endsWith(separator) ? topPart.substring(0, topPart.length - separator.length).trim() : topPart; | |
| // Finde den Start der alten Patch-Sektion im oberen Teil | |
| const firstPatchIndex = cleanTopPart.indexOf(patchHeader); | |
| // Die "Basis-Notes" sind alles vor dem ersten Patch. | |
| const baseNotes = firstPatchIndex !== -1 ? cleanTopPart.substring(0, firstPatchIndex).trim() : cleanTopPart; | |
| // Die Installations-Sektion kommt direkt aus dem Template (inkl. Header). | |
| const installSection = installNotes.trim(); | |
| // 4. Baue den neuen Body in der gewünschten Reihenfolge zusammen: Basis + Installation + Patches | |
| const newBody = `${baseNotes}\n\n${separator}\n\n${installSection}\n\n${patchNotes.trim()}`; | |
| // 5. Update the release | |
| await github.rest.repos.updateRelease({ owner, repo, release_id: latestRelease.id, body: newBody }); | |
| console.log("✅ Release Body wurde erfolgreich mit Patch-Informationen aktualisiert."); | |
| update_readme_on_release: | |
| name: 📚 Update README on Release | |
| needs: [analyze_changes] | |
| if: success() && needs.analyze_changes.outputs.update_type == 'release' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v3 | |
| with: | |
| fetch-depth: 0 | |
| - name: 🏗 Assemble README.md | |
| run: | | |
| # Inputs holen | |
| SUMMARY="${{ needs.analyze_changes.outputs.summary }}" | |
| DATE=$(date +'%d.%m.%Y') | |
| # Prüfen ob Templates existieren | |
| if [ ! -f .github/templates/README_BASE.md ]; then | |
| echo "WARNUNG: .github/templates/README_BASE.md fehlt! Breche ab." | |
| exit 1 | |
| fi | |
| # 1. Base laden (Alles überschreiben) | |
| cat .github/templates/README_BASE.md > README.md | |
| # 2. KI Sektion einbauen | |
| echo -e "\n---\n" >> README.md | |
| echo -e "## 🚀 Neuestes Update ($DATE)\n" >> README.md | |
| echo -e "$SUMMARY\n" >> README.md | |
| echo -e "👉 [**Komplette Update-Historie ansehen**](CHANGELOG.md)\n" >> README.md | |
| # 3. Installation anhängen | |
| if [ -f .github/templates/INSTALLATION.md ]; then | |
| echo -e "---\n" >> README.md | |
| cat .github/templates/INSTALLATION.md >> README.md | |
| fi | |
| - name: 🚀 Commit & Push changes | |
| run: | | |
| git config --global user.name "TechAna Bot" | |
| git config --global user.email "bot@techana.app" | |
| # Fix: Ensure we are on the correct branch and sync with remote changes from the previous job | |
| git checkout ${{ github.ref_name }} | |
| git pull origin ${{ github.ref_name }} | |
| if [[ -n $(git status -s README.md) ]]; then | |
| git add README.md | |
| git commit -m "docs: Rebuild README with latest changes [skip ci]" | |
| git push | |
| else | |
| echo "No changes in README." | |
| fi |