diff --git a/.github/workflows/registry-source.yaml b/.github/workflows/registry-source.yaml index 0fdd3db..d39fe46 100644 --- a/.github/workflows/registry-source.yaml +++ b/.github/workflows/registry-source.yaml @@ -23,6 +23,11 @@ on: required: false type: boolean default: false + allow_bootstrap: + description: 'Onboarding only: permit a single-day rebuild when no asset has ever been published' + required: false + type: boolean + default: false # Keyed on the source: without it every matrix leg shares one group and the legs cancel # each other, which is the opposite of running them in parallel. @@ -70,8 +75,9 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SOURCE: ${{ inputs.source }} RUN_DATE: ${{ inputs.date }} + BOOTSTRAP: ${{ inputs.allow_bootstrap && '1' || '' }} run: | - python "src/create_daily_${SOURCE}_release.py" ${RUN_DATE:+--date "$RUN_DATE"} + python "src/create_daily_${SOURCE}_release.py" ${RUN_DATE:+--date "$RUN_DATE"} ${BOOTSTRAP:+--allow-bootstrap} # Stage into one directory so every leg's artifact has the same root; a second # search path would move the root to the common ancestor for some legs only. shopt -s nullglob @@ -93,4 +99,6 @@ jobs: name: registry-${{ inputs.source }} path: data/registry-out retention-days: 1 - if-no-files-found: error + # A tolerated source that failed has nothing to upload; only a required + # source missing its artifact is an error. + if-no-files-found: ${{ inputs.required && 'error' || 'ignore' }} diff --git a/src/create_daily_faa_release.py b/src/create_daily_faa_release.py index b668518..8e5e49f 100644 --- a/src/create_daily_faa_release.py +++ b/src/create_daily_faa_release.py @@ -4,6 +4,10 @@ import argparse parser = argparse.ArgumentParser(description="Create daily FAA release") parser.add_argument("--date", type=str, help="Date to process (YYYY-MM-DD format, default: today)") +parser.add_argument("--allow-bootstrap", action="store_true", + help="Permit rebuilding from a single day when no published asset is found. " + "Onboarding only: a missing asset is otherwise indistinguishable from a " + "transient outage, and rebuilding would erase the accumulated history.") args = parser.parse_args() if args.date: @@ -43,7 +47,13 @@ df_new = convert_faa_master_txt_to_df(zip_path, date_str) try: df_base, start_date_str = get_latest_aircraft_faa_csv_df() except FileNotFoundError as e: - print(f"No existing FAA release found, bootstrapping from today only: {e}") + if not args.allow_bootstrap: + raise SystemExit( + f"No published FAA asset found: {e}\n" + "This is indistinguishable from a transient outage, and rebuilding from one day " + "would erase the accumulated history. Pass --allow-bootstrap when onboarding." + ) from None + print(f"Bootstrapping FAA from today only (--allow-bootstrap): {e}") df_base = None start_date_str = date_str diff --git a/src/create_daily_tc_release.py b/src/create_daily_tc_release.py index ecfc508..ba7ae3b 100644 --- a/src/create_daily_tc_release.py +++ b/src/create_daily_tc_release.py @@ -4,6 +4,10 @@ import argparse parser = argparse.ArgumentParser(description="Create daily Transport Canada release") parser.add_argument("--date", type=str, help="Date to process (YYYY-MM-DD format, default: today)") +parser.add_argument("--allow-bootstrap", action="store_true", + help="Permit rebuilding from a single day when no published asset is found. " + "Onboarding only: a missing asset is otherwise indistinguishable from a " + "transient outage, and rebuilding would erase the accumulated history.") args = parser.parse_args() if args.date: @@ -57,7 +61,13 @@ df_new = convert_tc_ccarcs_to_df(zip_path, date_str) try: df_base, start_date_str = get_latest_aircraft_tc_csv_df() except FileNotFoundError as e: - print(f"No existing Transport Canada release found, bootstrapping from today only: {e}") + if not args.allow_bootstrap: + raise SystemExit( + f"No published Transport Canada asset found: {e}\n" + "This is indistinguishable from a transient outage, and rebuilding from one day " + "would erase the accumulated history. Pass --allow-bootstrap when onboarding." + ) from None + print(f"Bootstrapping Transport Canada from today only (--allow-bootstrap): {e}") df_base = None start_date_str = date_str