Skip to content

Weather Predictions (every 3 h) #492

Weather Predictions (every 3 h)

Weather Predictions (every 3 h) #492

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