Weather Predictions (every 3 h) #492
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: Weather Predictions (every 3 h) | |
| on: | |
| schedule: | |
| # Runs at 00:00, 03:00, 06:00, 09:00, 12:00, 15:00, 18:00, 21:00 UTC. | |
| # That's 8 runs/day × 14 cities = 112 API calls/day (well within the | |
| # Open-Meteo 10k/day free tier) and ~25–40 min of CI runner time per | |
| # day (within the 2000 min/month free tier). | |
| - cron: '0 */3 * * *' | |
| # Allow manual runs from the Actions tab. | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| concurrency: | |
| # We serialize runs so two cron fires do not race on the commit step. | |
| group: weather-predictions | |
| cancel-in-progress: false | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUST_BACKTRACE: 1 | |
| jobs: | |
| predict: | |
| name: Run daily predictions (v2.0) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: true | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| toolchain: stable | |
| - name: Cache cargo dependencies | |
| uses: actions/cache@v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ${{ runner.os }}-cargo-release-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: | | |
| ${{ runner.os }}-cargo-release- | |
| - name: Verify production artifacts are present | |
| run: | | |
| set -e | |
| for f in \ | |
| models/scaler.json \ | |
| models/ridge_manual.json \ | |
| models/ridge_48h_manual.json \ | |
| models/ridge_72h_manual.json \ | |
| models/rain_rf_model.bin \ | |
| models/rain_bagging_ensemble.bin \ | |
| models/rain_calibration.json \ | |
| models/climatology.json \ | |
| models/drift_reference.json \ | |
| models/production_contract.json \ | |
| models/golden_test.json \ | |
| ; do | |
| test -f "$f" || { echo "Missing artifact: $f"; exit 1; } | |
| done | |
| echo "All production artifacts present." | |
| - name: Golden equivalence test (8 invariants) | |
| run: cargo test --release --test integration_loadmodel -- --nocapture | |
| - name: Build release binary | |
| run: cargo build --release --bin daily_predictions | |
| - name: Run daily predictions | |
| run: ./target/release/daily_predictions | |
| - name: Commit updated outputs | |
| run: | | |
| git config user.name "rust-weather-ml-bot" | |
| git config user.email "actions@github.com" | |
| git add README.md \ | |
| data/predictions/ \ | |
| data/monitoring_history/ \ | |
| docs/dashboard/ 2>/dev/null || true | |
| if git diff --cached --quiet; then | |
| echo "No changes to commit." | |
| else | |
| STAMP=$(date -u +%Y-%m-%dT%HZ) | |
| git commit -m "weather: predictions run ${STAMP} [ci skip]" | |
| BRANCH=${GITHUB_REF#refs/heads/} | |
| # Retry up to 3x: a concurrent push (bot ou humano) pode ter avançado | |
| # o remoto. Em conflito no README.md preferimos a versão recém-gerada | |
| # com as previsões (-X theirs no rebase). | |
| for attempt in 1 2 3; do | |
| git fetch origin "$BRANCH" | |
| if git rebase -X theirs "origin/$BRANCH"; then | |
| if git push origin "HEAD:$BRANCH"; then | |
| echo "Pushed on attempt $attempt." | |
| exit 0 | |
| fi | |
| else | |
| git rebase --abort || true | |
| fi | |
| sleep 5 | |
| done | |
| echo "Failed to push after 3 attempts." >&2 | |
| exit 1 | |
| fi |