Scheduled Updates (Firmware, Hardware, Translations) #7603
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: Scheduled Updates (Firmware, Hardware, Translations) | |
| on: | |
| schedule: | |
| # Hourly. This job is cheap (curl + Crowdin + PR, no build) — the slow | |
| # emulator/graph work lives in scheduled-baseline.yml on a daily cron. | |
| - cron: '0 * * * *' | |
| workflow_dispatch: # Allow manual triggering | |
| jobs: | |
| update_assets: | |
| runs-on: ubuntu-24.04 | |
| if: github.repository == 'meshtastic/Meshtastic-Android' | |
| permissions: | |
| contents: write # To commit files and push branches | |
| pull-requests: write # To create pull requests | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v7.0.1 | |
| with: | |
| token: ${{ secrets.CROWDIN_GITHUB_TOKEN }} | |
| - name: Update firmware releases list | |
| id: firmware | |
| run: | | |
| firmware_file_path="androidApp/src/main/assets/firmware_releases.json" | |
| temp_firmware_file="/tmp/new_firmware_releases.json" | |
| echo "Fetching latest firmware releases..." | |
| http_code=$(curl -s -o "$temp_firmware_file" -w '%{http_code}' https://api.meshtastic.org/github/firmware/list || true) | |
| http_code="${http_code:-0}" | |
| if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then | |
| echo "::warning::Firmware API returned HTTP $http_code. Skipping firmware update." | |
| echo "status=error" >> "$GITHUB_OUTPUT" | |
| echo "detail=HTTP $http_code from firmware API" >> "$GITHUB_OUTPUT" | |
| elif ! jq empty "$temp_firmware_file" 2>/dev/null; then | |
| echo "::warning::Firmware API returned invalid JSON data. Skipping firmware update." | |
| echo "status=error" >> "$GITHUB_OUTPUT" | |
| echo "detail=Invalid JSON response from firmware API" >> "$GITHUB_OUTPUT" | |
| else | |
| if [ ! -f "$firmware_file_path" ] || ! jq --sort-keys . "$temp_firmware_file" | diff -q - <(jq --sort-keys . "$firmware_file_path"); then | |
| echo "Changes detected in firmware list or local file missing. Updating $firmware_file_path." | |
| cp "$temp_firmware_file" "$firmware_file_path" | |
| echo "status=updated" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "No changes detected in firmware list." | |
| echo "status=unchanged" >> "$GITHUB_OUTPUT" | |
| fi | |
| fi | |
| - name: Update hardware list | |
| id: hardware | |
| run: | | |
| hardware_file_path="androidApp/src/main/assets/device_hardware.json" | |
| temp_hardware_file="/tmp/new_device_hardware.json" | |
| echo "Fetching latest device hardware data..." | |
| http_code=$(curl -s -o "$temp_hardware_file" -w '%{http_code}' https://api.meshtastic.org/resource/deviceHardware || true) | |
| http_code="${http_code:-0}" | |
| if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then | |
| echo "::warning::Hardware API returned HTTP $http_code. Skipping hardware update." | |
| echo "status=error" >> "$GITHUB_OUTPUT" | |
| echo "detail=HTTP $http_code from hardware API" >> "$GITHUB_OUTPUT" | |
| elif ! jq empty "$temp_hardware_file" 2>/dev/null; then | |
| echo "::warning::Hardware API returned invalid JSON data. Skipping hardware update." | |
| echo "status=error" >> "$GITHUB_OUTPUT" | |
| echo "detail=Invalid JSON response from hardware API" >> "$GITHUB_OUTPUT" | |
| else | |
| if [ ! -f "$hardware_file_path" ] || ! jq --sort-keys . "$temp_hardware_file" | diff -q - <(jq --sort-keys . "$hardware_file_path"); then | |
| echo "Changes detected in hardware list or local file missing. Updating $hardware_file_path." | |
| cp "$temp_hardware_file" "$hardware_file_path" | |
| echo "status=updated" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "No changes detected in hardware list." | |
| echo "status=unchanged" >> "$GITHUB_OUTPUT" | |
| fi | |
| fi | |
| - name: Update event firmware metadata | |
| id: event_firmware | |
| run: | | |
| event_firmware_file_path="androidApp/src/main/assets/event_firmware.json" | |
| temp_event_firmware_file="/tmp/new_event_firmware.json" | |
| echo "Fetching latest event firmware metadata..." | |
| http_code=$(curl -s --max-time 90 -o "$temp_event_firmware_file" -w '%{http_code}' https://api.meshtastic.org/resource/eventFirmware || true) | |
| http_code="${http_code:-0}" | |
| if [ "$http_code" -lt 200 ] || [ "$http_code" -ge 300 ]; then | |
| echo "::warning::Event firmware API returned HTTP $http_code. Skipping event firmware update." | |
| echo "status=error" >> "$GITHUB_OUTPUT" | |
| echo "detail=HTTP $http_code from event firmware API" >> "$GITHUB_OUTPUT" | |
| elif ! jq empty "$temp_event_firmware_file" 2>/dev/null; then | |
| echo "::warning::Event firmware API returned invalid JSON data. Skipping event firmware update." | |
| echo "status=error" >> "$GITHUB_OUTPUT" | |
| echo "detail=Invalid JSON response from event firmware API" >> "$GITHUB_OUTPUT" | |
| else | |
| if [ ! -f "$event_firmware_file_path" ] || ! jq --sort-keys . "$temp_event_firmware_file" | diff -q - <(jq --sort-keys . "$event_firmware_file_path"); then | |
| echo "Changes detected in event firmware metadata or local file missing. Updating $event_firmware_file_path." | |
| cp "$temp_event_firmware_file" "$event_firmware_file_path" | |
| echo "status=updated" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "No changes detected in event firmware metadata." | |
| echo "status=unchanged" >> "$GITHUB_OUTPUT" | |
| fi | |
| fi | |
| - name: Sync with Crowdin | |
| uses: crowdin/github-action@v2 | |
| with: | |
| base_url: 'https://meshtastic.crowdin.com/api/v2' | |
| config: 'crowdin.yml' | |
| crowdin_branch_name: 'main' | |
| upload_sources: true | |
| upload_sources_args: '--preserve-hierarchy' | |
| upload_translations: false | |
| download_translations: true | |
| download_translations_args: '--preserve-hierarchy' | |
| create_pull_request: false | |
| commit_message: 'chore(l10n): New Crowdin Translations from scheduled update' | |
| push_translations: false | |
| push_sources: false | |
| localization_branch_name: ${{ github.ref_name }} | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.CROWDIN_GITHUB_TOKEN }} | |
| CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} | |
| CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} | |
| - name: Fix file permissions | |
| run: sudo chown -R $USER:$USER . | |
| # Early warning for overlength store-listing translations just pulled from | |
| # Crowdin. Non-blocking on purpose: a hard failure here would abort the job | |
| # and stop the PR from being created. The hard gate is the check-metadata | |
| # job in pull-request.yml, which runs against the PR this workflow opens. | |
| - name: Check store metadata lengths | |
| continue-on-error: true | |
| run: python3 scripts/check-metadata-length.py | |
| - name: Build PR body | |
| id: pr_body | |
| env: | |
| # Hoisted into env: (not interpolated directly in the script) so no step output can inject shell — see | |
| # zizmor template-injection. Values are fixed strings today, but detail may carry API text in future. | |
| FIRMWARE_STATUS: ${{ steps.firmware.outputs.status }} | |
| FIRMWARE_DETAIL: ${{ steps.firmware.outputs.detail }} | |
| HARDWARE_STATUS: ${{ steps.hardware.outputs.status }} | |
| HARDWARE_DETAIL: ${{ steps.hardware.outputs.detail }} | |
| EVENT_FIRMWARE_STATUS: ${{ steps.event_firmware.outputs.status }} | |
| EVENT_FIRMWARE_DETAIL: ${{ steps.event_firmware.outputs.detail }} | |
| run: | | |
| firmware_status="$FIRMWARE_STATUS" | |
| firmware_detail="$FIRMWARE_DETAIL" | |
| hardware_status="$HARDWARE_STATUS" | |
| hardware_detail="$HARDWARE_DETAIL" | |
| event_firmware_status="$EVENT_FIRMWARE_STATUS" | |
| event_firmware_detail="$EVENT_FIRMWARE_DETAIL" | |
| body="This PR includes automated updates from the scheduled workflow:" | |
| body+=$'\n' | |
| # Firmware status | |
| case "$firmware_status" in | |
| updated) body+=$'\n'"- ✅ \`firmware_releases.json\` updated from the Meshtastic API." ;; | |
| unchanged) body+=$'\n'"- ✔️ \`firmware_releases.json\` checked — no changes detected." ;; | |
| error) body+=$'\n'"- ⚠️ \`firmware_releases.json\` skipped — ${firmware_detail}." ;; | |
| *) body+=$'\n'"- ❓ \`firmware_releases.json\` — unknown status." ;; | |
| esac | |
| # Hardware status | |
| case "$hardware_status" in | |
| updated) body+=$'\n'"- ✅ \`device_hardware.json\` updated from the Meshtastic API." ;; | |
| unchanged) body+=$'\n'"- ✔️ \`device_hardware.json\` checked — no changes detected." ;; | |
| error) body+=$'\n'"- ⚠️ \`device_hardware.json\` skipped — ${hardware_detail}." ;; | |
| *) body+=$'\n'"- ❓ \`device_hardware.json\` — unknown status." ;; | |
| esac | |
| # Event firmware status | |
| case "$event_firmware_status" in | |
| updated) body+=$'\n'"- ✅ \`event_firmware.json\` updated from the Meshtastic API." ;; | |
| unchanged) body+=$'\n'"- ✔️ \`event_firmware.json\` checked — no changes detected." ;; | |
| error) body+=$'\n'"- ⚠️ \`event_firmware.json\` skipped — ${event_firmware_detail}." ;; | |
| *) body+=$'\n'"- ❓ \`event_firmware.json\` — unknown status." ;; | |
| esac | |
| # Crowdin (always attempted) | |
| body+=$'\n'"- Source strings were uploaded to Crowdin." | |
| body+=$'\n'"- Latest translations were downloaded from Crowdin (if available)." | |
| body+=$'\n' | |
| body+=$'\n'"Please review the changes." | |
| # Write multi-line body to output | |
| { | |
| echo "content<<PREOF" | |
| echo "$body" | |
| echo "PREOF" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Create Pull Request if changes occurred | |
| uses: peter-evans/create-pull-request@v8 | |
| with: | |
| token: ${{ secrets.CROWDIN_GITHUB_TOKEN }} | |
| commit-message: | | |
| chore: Scheduled updates (Firmware, Hardware, Translations) | |
| Automated updates for: | |
| - Firmware releases list | |
| - Device hardware list | |
| - Event firmware metadata | |
| - Crowdin source string uploads | |
| - Crowdin translation downloads | |
| title: 'chore: Scheduled updates (Firmware, Hardware, Translations)' | |
| body: ${{ steps.pr_body.outputs.content }} | |
| branch: 'scheduled-updates' | |
| base: 'main' | |
| delete-branch: true | |
| add-paths: | | |
| androidApp/src/main/assets/firmware_releases.json | |
| androidApp/src/main/assets/device_hardware.json | |
| androidApp/src/main/assets/event_firmware.json | |
| fastlane/metadata/android/** | |
| **/strings.xml | |
| docs/**/*.md | |
| labels: | | |
| automation | |
| l10n | |
| firmware | |
| hardware |