fix: stop a transient error erasing the FAA release history

- narrow the fallback to FileNotFoundError and move the monotonic assert out of the try:
  a rate limit, parse error or corrupt download previously rebuilt three years of registry
  from a single day and republished it as the whole dataset
- authenticate release reads and walk back through releases, matching the Transport Canada
  reader; the FAA path was unauthenticated at 60 requests an hour on shared runner IPs
- verify downloaded asset size

This is what the matrix's required: true flag on faa claims to protect, so the flag was
advertising a guarantee the script could not keep.

Generated-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Ashley Childress
2026-09-10 20:53:54 -04:00
parent f78fa1c3ee
commit e3c8a0e242
2 changed files with 35 additions and 14 deletions
+12 -5
View File
@@ -37,13 +37,20 @@ from derive_from_faa_master_txt import convert_faa_master_txt_to_df, concat_faa_
from get_latest_release import get_latest_aircraft_faa_csv_df from get_latest_release import get_latest_aircraft_faa_csv_df
df_new = convert_faa_master_txt_to_df(zip_path, date_str) df_new = convert_faa_master_txt_to_df(zip_path, date_str)
# Only a genuine first run may rebuild from a single day. A rate limit, a parse error or a
# non-monotonic download_date must stop the run: this file becomes tomorrow's base, so
# silently republishing one day erases the accumulated history.
try: try:
df_base, start_date_str = get_latest_aircraft_faa_csv_df() df_base, start_date_str = get_latest_aircraft_faa_csv_df()
df_base = concat_faa_historical_df(df_base, df_new) except FileNotFoundError as e:
assert df_base['download_date'].is_monotonic_increasing, "download_date is not monotonic increasing" print(f"No existing FAA release found, bootstrapping from today only: {e}")
except Exception as e: df_base = None
print(f"No existing FAA release found, using only new data: {e}")
df_base = df_new
start_date_str = date_str start_date_str = date_str
if df_base is not None:
df_base = concat_faa_historical_df(df_base, df_new)
assert df_base['download_date'].is_monotonic_increasing, "download_date is not monotonic increasing"
else:
df_base = df_new
df_base.to_csv(OUT_ROOT / f"openairframes_faa_{start_date_str}_{date_str}.csv", index=False) df_base.to_csv(OUT_ROOT / f"openairframes_faa_{start_date_str}_{date_str}.csv", index=False)
+23 -9
View File
@@ -139,15 +139,29 @@ def download_latest_aircraft_csv(
Path to the downloaded file Path to the downloaded file
""" """
output_dir = Path(output_dir) output_dir = Path(output_dir)
assets = get_latest_release_assets(repo, github_token=github_token) github_token = github_token or os.environ.get("GITHUB_TOKEN")
try:
asset = pick_asset(assets, name_regex=r"^openairframes_faa_.*\.csv$") for release in get_releases(repo, github_token=github_token, per_page=30):
except FileNotFoundError: assets = get_release_assets_from_release_data(release)
# Fallback to old naming pattern try:
asset = pick_asset(assets, name_regex=r"^openairframes_\d{4}-\d{2}-\d{2}_.*\.csv$") asset = pick_asset(assets, name_regex=r"^openairframes_faa_.*\.csv$")
saved_to = download_asset(asset, output_dir / asset.name, github_token=github_token) except FileNotFoundError:
print(f"Downloaded: {asset.name} ({asset.size} bytes) -> {saved_to}") try:
return saved_to # Fallback to old naming pattern
asset = pick_asset(assets, name_regex=r"^openairframes_\d{4}-\d{2}-\d{2}_.*\.csv$")
except FileNotFoundError:
continue
saved_to = download_asset(asset, output_dir / asset.name, github_token=github_token)
if asset.size and saved_to.stat().st_size != asset.size:
raise RuntimeError(
f"{asset.name}: downloaded {saved_to.stat().st_size} bytes, expected {asset.size}"
)
print(f"Downloaded: {asset.name} ({asset.size} bytes) -> {saved_to}")
return saved_to
raise FileNotFoundError(
"No release in the last 30 releases has an asset matching 'openairframes_faa_.*\\.csv$'"
)
def get_latest_aircraft_faa_csv_df(): def get_latest_aircraft_faa_csv_df():
csv_path = download_latest_aircraft_csv() csv_path = download_latest_aircraft_csv()