il2ks 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- il2ks-0.1.0/.dockerignore +12 -0
- il2ks-0.1.0/.gitattributes +2 -0
- il2ks-0.1.0/.github/scripts/run-installer.ps1 +40 -0
- il2ks-0.1.0/.github/workflows/ci.yml +125 -0
- il2ks-0.1.0/.github/workflows/loadtest.yml +38 -0
- il2ks-0.1.0/.github/workflows/release.yml +119 -0
- il2ks-0.1.0/.github/workflows/windows-installer.yml +232 -0
- il2ks-0.1.0/.gitignore +243 -0
- il2ks-0.1.0/.pre-commit-config.yaml +13 -0
- il2ks-0.1.0/.python-version +1 -0
- il2ks-0.1.0/CHANGELOG.md +5 -0
- il2ks-0.1.0/CLAUDE.md +65 -0
- il2ks-0.1.0/LICENSE +21 -0
- il2ks-0.1.0/NOTICE +93 -0
- il2ks-0.1.0/PKG-INFO +119 -0
- il2ks-0.1.0/README.md +94 -0
- il2ks-0.1.0/design_doc/01_context_and_goals.md +58 -0
- il2ks-0.1.0/design_doc/02_functional_requirements.md +322 -0
- il2ks-0.1.0/design_doc/03_non_functional_requirements.md +85 -0
- il2ks-0.1.0/design_doc/04_architecture.md +159 -0
- il2ks-0.1.0/design_doc/05_technical_decisions.md +406 -0
- il2ks-0.1.0/design_doc/06_data_model.md +280 -0
- il2ks-0.1.0/design_doc/07_deployment_and_installation.md +138 -0
- il2ks-0.1.0/design_doc/08_development_workflow.md +113 -0
- il2ks-0.1.0/design_doc/09_legacy_system_notes.md +97 -0
- il2ks-0.1.0/design_doc/10_roadmap.md +358 -0
- il2ks-0.1.0/design_doc/11_open_questions.md +33 -0
- il2ks-0.1.0/design_doc/12_korea_log_format.md +286 -0
- il2ks-0.1.0/design_doc/13_game_rules.md +603 -0
- il2ks-0.1.0/design_doc/14_ingest_internals.md +410 -0
- il2ks-0.1.0/design_doc/15_visual_assets.md +340 -0
- il2ks-0.1.0/design_doc/16_web_and_operations.md +447 -0
- il2ks-0.1.0/design_doc/17_achievements.md +340 -0
- il2ks-0.1.0/design_doc/README.md +111 -0
- il2ks-0.1.0/docker/.env.example +40 -0
- il2ks-0.1.0/docker/Dockerfile +75 -0
- il2ks-0.1.0/docker/compose.dev.yaml +16 -0
- il2ks-0.1.0/docker/compose.yaml +63 -0
- il2ks-0.1.0/docker/docker-entrypoint.sh +56 -0
- il2ks-0.1.0/docker/smoke-test.sh +119 -0
- il2ks-0.1.0/docs/customizing.md +352 -0
- il2ks-0.1.0/docs/install-docker.md +194 -0
- il2ks-0.1.0/docs/install-windows.md +163 -0
- il2ks-0.1.0/docs/install.md +302 -0
- il2ks-0.1.0/docs/performance-testing.md +233 -0
- il2ks-0.1.0/docs/releasing.md +57 -0
- il2ks-0.1.0/docs/reverse-proxy.md +142 -0
- il2ks-0.1.0/docs/settings.md +224 -0
- il2ks-0.1.0/docs/translating.md +208 -0
- il2ks-0.1.0/loadtest/locustfile.py +188 -0
- il2ks-0.1.0/loadtest/run.py +106 -0
- il2ks-0.1.0/packaging/windows/README.md +103 -0
- il2ks-0.1.0/packaging/windows/build.py +373 -0
- il2ks-0.1.0/packaging/windows/files/il2ks-admin.cmd +28 -0
- il2ks-0.1.0/packaging/windows/files/il2ks.cmd +10 -0
- il2ks-0.1.0/packaging/windows/il2ks.iss +804 -0
- il2ks-0.1.0/packaging/windows/pins.toml +36 -0
- il2ks-0.1.0/packaging/windows/quoting.py +22 -0
- il2ks-0.1.0/packaging/windows/winsw.py +84 -0
- il2ks-0.1.0/packaging/windows/zones.py +162 -0
- il2ks-0.1.0/pyproject.toml +140 -0
- il2ks-0.1.0/src/il2ks/__init__.py +3 -0
- il2ks-0.1.0/src/il2ks/__main__.py +7 -0
- il2ks-0.1.0/src/il2ks/cli.py +537 -0
- il2ks-0.1.0/src/il2ks/config.py +729 -0
- il2ks-0.1.0/src/il2ks/core/__init__.py +1 -0
- il2ks-0.1.0/src/il2ks/core/achievement_rules.py +83 -0
- il2ks-0.1.0/src/il2ks/core/achievements.py +473 -0
- il2ks-0.1.0/src/il2ks/core/catalog/__init__.py +1 -0
- il2ks-0.1.0/src/il2ks/core/catalog/data/ammo.csv +59 -0
- il2ks-0.1.0/src/il2ks/core/catalog/data/object_aliases.csv +2 -0
- il2ks-0.1.0/src/il2ks/core/catalog/data/object_names_de.csv +436 -0
- il2ks-0.1.0/src/il2ks/core/catalog/data/object_names_es.csv +439 -0
- il2ks-0.1.0/src/il2ks/core/catalog/data/object_names_fr.csv +437 -0
- il2ks-0.1.0/src/il2ks/core/catalog/data/object_names_pt-br.csv +439 -0
- il2ks-0.1.0/src/il2ks/core/catalog/data/object_names_ru.csv +470 -0
- il2ks-0.1.0/src/il2ks/core/catalog/data/objects.csv +490 -0
- il2ks-0.1.0/src/il2ks/core/catalog/data/ordnance.csv +33 -0
- il2ks-0.1.0/src/il2ks/core/catalog/data/payload_aliases.csv +13 -0
- il2ks-0.1.0/src/il2ks/core/catalog/data/payloads.csv +416 -0
- il2ks-0.1.0/src/il2ks/core/catalog/data/weapon_mod_names_de.csv +24 -0
- il2ks-0.1.0/src/il2ks/core/catalog/data/weapon_mod_names_es.csv +24 -0
- il2ks-0.1.0/src/il2ks/core/catalog/data/weapon_mod_names_fr.csv +24 -0
- il2ks-0.1.0/src/il2ks/core/catalog/data/weapon_mod_names_pt-br.csv +24 -0
- il2ks-0.1.0/src/il2ks/core/catalog/data/weapon_mod_names_ru.csv +24 -0
- il2ks-0.1.0/src/il2ks/core/catalog/data/weapon_mods.csv +34 -0
- il2ks-0.1.0/src/il2ks/core/catalog/loader.py +737 -0
- il2ks-0.1.0/src/il2ks/core/killboard.py +13 -0
- il2ks-0.1.0/src/il2ks/core/logparse/__init__.py +1 -0
- il2ks-0.1.0/src/il2ks/core/logparse/events.py +364 -0
- il2ks-0.1.0/src/il2ks/core/logparse/files.py +148 -0
- il2ks-0.1.0/src/il2ks/core/logparse/parser.py +950 -0
- il2ks-0.1.0/src/il2ks/core/logparse/tail.py +69 -0
- il2ks-0.1.0/src/il2ks/core/ratings/__init__.py +1 -0
- il2ks-0.1.0/src/il2ks/core/ratings/elo.py +191 -0
- il2ks-0.1.0/src/il2ks/core/ratings/score.py +171 -0
- il2ks-0.1.0/src/il2ks/core/replay/__init__.py +1 -0
- il2ks-0.1.0/src/il2ks/core/replay/ammo.py +604 -0
- il2ks-0.1.0/src/il2ks/core/replay/areas.py +66 -0
- il2ks-0.1.0/src/il2ks/core/replay/attack.py +166 -0
- il2ks-0.1.0/src/il2ks/core/replay/breakdown.py +251 -0
- il2ks-0.1.0/src/il2ks/core/replay/config.py +71 -0
- il2ks-0.1.0/src/il2ks/core/replay/credit.py +87 -0
- il2ks-0.1.0/src/il2ks/core/replay/damage.py +99 -0
- il2ks-0.1.0/src/il2ks/core/replay/fate.py +414 -0
- il2ks-0.1.0/src/il2ks/core/replay/hits.py +108 -0
- il2ks-0.1.0/src/il2ks/core/replay/judge.py +264 -0
- il2ks-0.1.0/src/il2ks/core/replay/kills.py +236 -0
- il2ks-0.1.0/src/il2ks/core/replay/live.py +142 -0
- il2ks-0.1.0/src/il2ks/core/replay/model.py +262 -0
- il2ks-0.1.0/src/il2ks/core/replay/pve.py +63 -0
- il2ks-0.1.0/src/il2ks/core/replay/rams.py +93 -0
- il2ks-0.1.0/src/il2ks/core/replay/resolve.py +223 -0
- il2ks-0.1.0/src/il2ks/core/replay/result.py +311 -0
- il2ks-0.1.0/src/il2ks/core/replay/state.py +523 -0
- il2ks-0.1.0/src/il2ks/core/replay/toggles.py +19 -0
- il2ks-0.1.0/src/il2ks/core/stat_marks.py +304 -0
- il2ks-0.1.0/src/il2ks/core/streaks.py +177 -0
- il2ks-0.1.0/src/il2ks/core/tours.py +143 -0
- il2ks-0.1.0/src/il2ks/data/il2ks.example.toml +329 -0
- il2ks-0.1.0/src/il2ks/db/__init__.py +1 -0
- il2ks-0.1.0/src/il2ks/db/apps.py +8 -0
- il2ks-0.1.0/src/il2ks/db/copy.py +30 -0
- il2ks-0.1.0/src/il2ks/db/migrations/0001_initial.py +3023 -0
- il2ks-0.1.0/src/il2ks/db/migrations/__init__.py +0 -0
- il2ks-0.1.0/src/il2ks/db/models.py +2039 -0
- il2ks-0.1.0/src/il2ks/db/reprocess_requests.py +43 -0
- il2ks-0.1.0/src/il2ks/db/site.py +59 -0
- il2ks-0.1.0/src/il2ks/db/validators.py +29 -0
- il2ks-0.1.0/src/il2ks/devtools/__init__.py +1 -0
- il2ks-0.1.0/src/il2ks/devtools/anonymize.py +73 -0
- il2ks-0.1.0/src/il2ks/devtools/assets.py +565 -0
- il2ks-0.1.0/src/il2ks/devtools/bailout_eval.py +217 -0
- il2ks-0.1.0/src/il2ks/devtools/bench.py +221 -0
- il2ks-0.1.0/src/il2ks/devtools/check.py +336 -0
- il2ks-0.1.0/src/il2ks/devtools/dbdump.py +40 -0
- il2ks-0.1.0/src/il2ks/devtools/migrations.py +154 -0
- il2ks-0.1.0/src/il2ks/devtools/templates.py +60 -0
- il2ks-0.1.0/src/il2ks/devtools/translations.py +354 -0
- il2ks-0.1.0/src/il2ks/exitcodes.py +7 -0
- il2ks-0.1.0/src/il2ks/ingest/__init__.py +1 -0
- il2ks-0.1.0/src/il2ks/ingest/achievements.py +479 -0
- il2ks-0.1.0/src/il2ks/ingest/activity.py +54 -0
- il2ks-0.1.0/src/il2ks/ingest/aggregates.py +647 -0
- il2ks-0.1.0/src/il2ks/ingest/aircraft_mods.py +166 -0
- il2ks-0.1.0/src/il2ks/ingest/aircraft_stats.py +788 -0
- il2ks-0.1.0/src/il2ks/ingest/archive.py +183 -0
- il2ks-0.1.0/src/il2ks/ingest/batch.py +168 -0
- il2ks-0.1.0/src/il2ks/ingest/builds.py +78 -0
- il2ks-0.1.0/src/il2ks/ingest/counters.py +135 -0
- il2ks-0.1.0/src/il2ks/ingest/dbutil.py +92 -0
- il2ks-0.1.0/src/il2ks/ingest/discover.py +187 -0
- il2ks-0.1.0/src/il2ks/ingest/flight_score.py +39 -0
- il2ks-0.1.0/src/il2ks/ingest/identity.py +97 -0
- il2ks-0.1.0/src/il2ks/ingest/live.py +468 -0
- il2ks-0.1.0/src/il2ks/ingest/lock.py +185 -0
- il2ks-0.1.0/src/il2ks/ingest/pairs.py +191 -0
- il2ks-0.1.0/src/il2ks/ingest/persist.py +911 -0
- il2ks-0.1.0/src/il2ks/ingest/rating_games.py +43 -0
- il2ks-0.1.0/src/il2ks/ingest/ratings.py +186 -0
- il2ks-0.1.0/src/il2ks/ingest/reprocess.py +303 -0
- il2ks-0.1.0/src/il2ks/ingest/reprocess_requests.py +104 -0
- il2ks-0.1.0/src/il2ks/ingest/rollup.py +125 -0
- il2ks-0.1.0/src/il2ks/ingest/rule_store.py +167 -0
- il2ks-0.1.0/src/il2ks/ingest/runner.py +417 -0
- il2ks-0.1.0/src/il2ks/ingest/score_apply.py +44 -0
- il2ks-0.1.0/src/il2ks/ingest/scoring.py +80 -0
- il2ks-0.1.0/src/il2ks/ingest/stat_marks.py +181 -0
- il2ks-0.1.0/src/il2ks/ingest/streaks.py +343 -0
- il2ks-0.1.0/src/il2ks/ingest/timeutil.py +86 -0
- il2ks-0.1.0/src/il2ks/ingest/tours.py +425 -0
- il2ks-0.1.0/src/il2ks/ingest/type_board.py +158 -0
- il2ks-0.1.0/src/il2ks/ingest/watch.py +153 -0
- il2ks-0.1.0/src/il2ks/ingest/worker.py +45 -0
- il2ks-0.1.0/src/il2ks/locale/de/LC_MESSAGES/django.mo +0 -0
- il2ks-0.1.0/src/il2ks/locale/de/LC_MESSAGES/django.po +6781 -0
- il2ks-0.1.0/src/il2ks/locale/es/LC_MESSAGES/django.mo +0 -0
- il2ks-0.1.0/src/il2ks/locale/es/LC_MESSAGES/django.po +6767 -0
- il2ks-0.1.0/src/il2ks/locale/fr/LC_MESSAGES/django.mo +0 -0
- il2ks-0.1.0/src/il2ks/locale/fr/LC_MESSAGES/django.po +6798 -0
- il2ks-0.1.0/src/il2ks/locale/pt_BR/LC_MESSAGES/django.mo +0 -0
- il2ks-0.1.0/src/il2ks/locale/pt_BR/LC_MESSAGES/django.po +6747 -0
- il2ks-0.1.0/src/il2ks/locale/ru/LC_MESSAGES/django.mo +0 -0
- il2ks-0.1.0/src/il2ks/locale/ru/LC_MESSAGES/django.po +6754 -0
- il2ks-0.1.0/src/il2ks/logsetup.py +186 -0
- il2ks-0.1.0/src/il2ks/ops/__init__.py +1 -0
- il2ks-0.1.0/src/il2ks/ops/admin.py +108 -0
- il2ks-0.1.0/src/il2ks/ops/backup.py +478 -0
- il2ks-0.1.0/src/il2ks/ops/checks.py +552 -0
- il2ks-0.1.0/src/il2ks/ops/commands.py +293 -0
- il2ks-0.1.0/src/il2ks/ops/dbfile.py +58 -0
- il2ks-0.1.0/src/il2ks/ops/detect.py +181 -0
- il2ks-0.1.0/src/il2ks/ops/doctor.py +54 -0
- il2ks-0.1.0/src/il2ks/ops/migrate.py +250 -0
- il2ks-0.1.0/src/il2ks/ops/prompt.py +63 -0
- il2ks-0.1.0/src/il2ks/ops/report.py +86 -0
- il2ks-0.1.0/src/il2ks/ops/serving_checks.py +267 -0
- il2ks-0.1.0/src/il2ks/ops/setup.py +521 -0
- il2ks-0.1.0/src/il2ks/ops/template.py +133 -0
- il2ks-0.1.0/src/il2ks/queries/__init__.py +1 -0
- il2ks-0.1.0/src/il2ks/queries/achievements.py +85 -0
- il2ks-0.1.0/src/il2ks/queries/activity.py +24 -0
- il2ks-0.1.0/src/il2ks/queries/aircraft.py +525 -0
- il2ks-0.1.0/src/il2ks/queries/ammo.py +261 -0
- il2ks-0.1.0/src/il2ks/queries/boards.py +180 -0
- il2ks-0.1.0/src/il2ks/queries/builds.py +54 -0
- il2ks-0.1.0/src/il2ks/queries/leaderboards.py +393 -0
- il2ks-0.1.0/src/il2ks/queries/live.py +114 -0
- il2ks-0.1.0/src/il2ks/queries/missions.py +207 -0
- il2ks-0.1.0/src/il2ks/queries/paging.py +15 -0
- il2ks-0.1.0/src/il2ks/queries/players.py +243 -0
- il2ks-0.1.0/src/il2ks/queries/sorties.py +217 -0
- il2ks-0.1.0/src/il2ks/queries/sorting.py +76 -0
- il2ks-0.1.0/src/il2ks/queries/stat_marks.py +29 -0
- il2ks-0.1.0/src/il2ks/queries/tours.py +184 -0
- il2ks-0.1.0/src/il2ks/rule_settings.py +219 -0
- il2ks-0.1.0/src/il2ks/serving/__init__.py +2 -0
- il2ks-0.1.0/src/il2ks/serving/_vendor/LICENSE-rjsmin-rcssmin.txt +201 -0
- il2ks-0.1.0/src/il2ks/serving/_vendor/__init__.py +1 -0
- il2ks-0.1.0/src/il2ks/serving/_vendor/rcssmin.py +436 -0
- il2ks-0.1.0/src/il2ks/serving/_vendor/rjsmin.py +594 -0
- il2ks-0.1.0/src/il2ks/serving/bootid.py +25 -0
- il2ks-0.1.0/src/il2ks/serving/caddy.py +219 -0
- il2ks-0.1.0/src/il2ks/serving/commands.py +653 -0
- il2ks-0.1.0/src/il2ks/serving/custom.py +395 -0
- il2ks-0.1.0/src/il2ks/serving/djsettings.py +130 -0
- il2ks-0.1.0/src/il2ks/serving/procutil.py +257 -0
- il2ks-0.1.0/src/il2ks/serving/secret.py +50 -0
- il2ks-0.1.0/src/il2ks/serving/service.py +160 -0
- il2ks-0.1.0/src/il2ks/serving/setup_token.py +195 -0
- il2ks-0.1.0/src/il2ks/serving/storage.py +70 -0
- il2ks-0.1.0/src/il2ks/serving/supervisor.py +269 -0
- il2ks-0.1.0/src/il2ks/serving/templateversions.py +303 -0
- il2ks-0.1.0/src/il2ks/serving/webserver.py +71 -0
- il2ks-0.1.0/src/il2ks/settings.py +173 -0
- il2ks-0.1.0/src/il2ks/urls.py +11 -0
- il2ks-0.1.0/src/il2ks/web/__init__.py +1 -0
- il2ks-0.1.0/src/il2ks/web/achievement_config.py +112 -0
- il2ks-0.1.0/src/il2ks/web/admin.py +802 -0
- il2ks-0.1.0/src/il2ks/web/admin_achievements.py +196 -0
- il2ks-0.1.0/src/il2ks/web/admin_config.py +8 -0
- il2ks-0.1.0/src/il2ks/web/admin_quips.py +170 -0
- il2ks-0.1.0/src/il2ks/web/admin_rules.py +178 -0
- il2ks-0.1.0/src/il2ks/web/admin_score.py +28 -0
- il2ks-0.1.0/src/il2ks/web/admin_site.py +298 -0
- il2ks-0.1.0/src/il2ks/web/apps.py +6 -0
- il2ks-0.1.0/src/il2ks/web/branding_images.py +140 -0
- il2ks-0.1.0/src/il2ks/web/caching.py +124 -0
- il2ks-0.1.0/src/il2ks/web/chart_data.py +84 -0
- il2ks-0.1.0/src/il2ks/web/charts.py +197 -0
- il2ks-0.1.0/src/il2ks/web/column_hints.py +209 -0
- il2ks-0.1.0/src/il2ks/web/columns.py +295 -0
- il2ks-0.1.0/src/il2ks/web/context_processors.py +119 -0
- il2ks-0.1.0/src/il2ks/web/display.py +324 -0
- il2ks-0.1.0/src/il2ks/web/feature_image.py +307 -0
- il2ks-0.1.0/src/il2ks/web/flavor.py +458 -0
- il2ks-0.1.0/src/il2ks/web/fonts.py +146 -0
- il2ks-0.1.0/src/il2ks/web/ground.py +58 -0
- il2ks-0.1.0/src/il2ks/web/icons.py +140 -0
- il2ks-0.1.0/src/il2ks/web/ingest_status.py +100 -0
- il2ks-0.1.0/src/il2ks/web/logo.py +128 -0
- il2ks-0.1.0/src/il2ks/web/medals.py +380 -0
- il2ks-0.1.0/src/il2ks/web/media.py +59 -0
- il2ks-0.1.0/src/il2ks/web/object_names.py +33 -0
- il2ks-0.1.0/src/il2ks/web/pve.py +84 -0
- il2ks-0.1.0/src/il2ks/web/quips.py +140 -0
- il2ks-0.1.0/src/il2ks/web/setup_forms.py +154 -0
- il2ks-0.1.0/src/il2ks/web/site_forms.py +473 -0
- il2ks-0.1.0/src/il2ks/web/sortie_view.py +870 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/il2ks.js +209 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/README.md +130 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/aircraft/generic-jet.svg +1 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/aircraft/generic-prop.svg +1 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/aircraft/unknown.svg +1 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/brand/favicon.svg +1 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/brand/logo-mark.svg +1 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/coalition/blufor.svg +11 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/coalition/insignia/kpaf.svg +1 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/coalition/insignia/plaaf.svg +1 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/coalition/insignia/rokaf.svg +1 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/coalition/insignia/un.svg +1 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/coalition/insignia/usaf.svg +1 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/coalition/insignia/vvs.svg +1 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/coalition/redfor.svg +11 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/event/assist.svg +14 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/event/bailout.svg +14 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/event/bomb-release.svg +13 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/event/damaged.svg +12 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/event/destroyed.svg +11 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/event/disconnect.svg +18 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/event/friendly-fire.svg +13 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/event/kill-air.svg +16 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/event/kill-ground.svg +13 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/event/landing.svg +12 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/event/ram.svg +18 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/event/rocket-salvo.svg +13 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/event/sortie-end.svg +13 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/event/spawn.svg +13 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/event/takeoff.svg +12 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/flag/br.svg +45 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/flag/de.svg +5 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/flag/es.svg +4 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/flag/fr.svg +5 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/flag/ru.svg +5 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/flag/us.svg +9 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/ground/aaa.svg +1 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/ground/artillery.svg +1 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/ground/building.svg +18 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/ground/other-static.svg +19 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/ground/parked-aircraft.svg +11 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/ground/ship.svg +14 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/ground/tank.svg +13 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/ground/train.svg +17 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/ground/vehicle.svg +13 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/illustration/404.svg +1 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/illustration/500.svg +1 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/illustration/empty.svg +1 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/ace-in-a-day.svg +19 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/career-kills.svg +16 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/damaged-landing.svg +15 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/elo-peak.svg +12 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/first-blood.svg +11 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/flight-hours.svg +12 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/frequent-flyer.svg +12 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/ground-score.svg +14 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/ground-sortie.svg +11 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/landing-streak.svg +12 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/life-kills.svg +14 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/multi-kill.svg +12 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/ram.svg +18 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/regular.svg +21 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/shame-crashed.svg +13 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/shame-friendly.svg +14 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/shame-strafed.svg +11 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/shame-taxi.svg +15 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/sortie-kills.svg +15 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/strike-hunter.svg +12 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/survivor.svg +12 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/tank-buster.svg +13 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/tours-in-a-row.svg +12 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/type-veteran.svg +13 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/types-flown.svg +13 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/medal/types-with-kills.svg +16 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/nav/book.svg +15 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/nav/discord.svg +14 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/nav/forum.svg +12 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/nav/github.svg +11 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/nav/link.svg +13 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/nav/mail.svg +12 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/nav/patreon.svg +11 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/nav/steam.svg +12 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/nav/telegram.svg +11 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/nav/twitch.svg +13 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/nav/youtube.svg +12 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/outcome/bailed-out.svg +14 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/outcome/captured.svg +18 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/outcome/crashed.svg +11 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/outcome/dead.svg +11 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/outcome/disconnected.svg +18 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/outcome/ditched.svg +13 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/outcome/exited-on-ground.svg +13 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/outcome/in-flight.svg +12 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/outcome/landed.svg +12 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/outcome/mission-ended.svg +13 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/outcome/not-taken-off.svg +12 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/outcome/shot-down.svg +12 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/outcome/unknown.svg +13 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/outcome/wounded.svg +15 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/pattern/camo.svg +18 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/role/air-superiority.svg +14 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/role/attack.svg +13 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/stat/accuracy.svg +13 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/stat/air-kills.svg +16 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/stat/assists.svg +14 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/stat/bailouts.svg +14 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/stat/captures.svg +18 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/stat/deaths.svg +15 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/stat/elo-jet.svg +12 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/stat/elo-prop.svg +15 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/stat/flight-time.svg +12 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/stat/friendly-fire.svg +15 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/stat/ground-hour.svg +13 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/stat/ground-kills.svg +13 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/stat/interception.svg +14 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/stat/planes-lost.svg +11 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/stat/play-time.svg +14 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/stat/sorties.svg +12 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/stat/strafed.svg +15 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/img/stat/taxi-accidents.svg +16 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/leaderboards.css +26 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/localtime.js +68 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/missions.css +65 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/players.css +129 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/setup.css +24 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/setup.js +15 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/site.css +769 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/sortie.js +15 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/sorties.css +83 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/theme-init.js +15 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/vendor/BarlowCondensed-600.woff2 +0 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/vendor/BarlowCondensed-700.woff2 +0 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/vendor/LICENSE-barlow-condensed-OFL.txt +93 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/vendor/LICENSE-htmx.txt +13 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/vendor/LICENSE-pico.md +21 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/vendor/README.md +18 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/vendor/htmx.min.js +1 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks/vendor/pico.min.css +4 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks_admin/ingest_status.css +15 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks_admin/override_warning.css +12 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks_admin/theme_editor.css +18 -0
- il2ks-0.1.0/src/il2ks/web/static/il2ks_admin/theme_editor.js +36 -0
- il2ks-0.1.0/src/il2ks/web/svg_symbol.py +128 -0
- il2ks-0.1.0/src/il2ks/web/template_versions.json +569 -0
- il2ks-0.1.0/src/il2ks/web/templates/404.html +17 -0
- il2ks-0.1.0/src/il2ks/web/templates/500.html +27 -0
- il2ks-0.1.0/src/il2ks/web/templates/admin/_rule_fields.html +23 -0
- il2ks-0.1.0/src/il2ks/web/templates/admin/base_site.html +22 -0
- il2ks-0.1.0/src/il2ks/web/templates/admin/il2ks_achievements.html +74 -0
- il2ks-0.1.0/src/il2ks/web/templates/admin/il2ks_db/tour/change_list.html +15 -0
- il2ks-0.1.0/src/il2ks/web/templates/admin/il2ks_index.html +55 -0
- il2ks-0.1.0/src/il2ks/web/templates/admin/il2ks_ingest_status.html +174 -0
- il2ks-0.1.0/src/il2ks/web/templates/admin/il2ks_leaderboards.html +21 -0
- il2ks-0.1.0/src/il2ks/web/templates/admin/il2ks_quips.html +74 -0
- il2ks-0.1.0/src/il2ks/web/templates/admin/il2ks_reprocess_confirm.html +23 -0
- il2ks-0.1.0/src/il2ks/web/templates/admin/il2ks_rules.html +21 -0
- il2ks-0.1.0/src/il2ks/web/templates/admin/il2ks_score.html +40 -0
- il2ks-0.1.0/src/il2ks/web/templates/admin/il2ks_tours.html +41 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/achievements/_award.html +5 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/achievements/_medal.html +12 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/achievements/_ribbon.html +12 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/achievements/holders.html +35 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/achievements/home_feed.html +24 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/achievements/overview.html +38 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/aircraft/detail.html +265 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/aircraft/list.html +65 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/aircraft/parts/ammo_mix_row.html +10 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/aircraft/top_elo.html +36 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/aircraft/top_ground.html +36 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/base.html +100 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/accordion.html +8 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/badge.html +6 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/bar_chart.html +47 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/breadcrumbs.html +9 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/col_hint.html +6 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/col_th.html +10 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/columns_picker.html +17 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/dropdown.html +10 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/empty_row.html +6 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/filter_bar.html +20 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/filter_select.html +10 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/filter_text.html +8 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/kv_list.html +7 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/language_menu.html +11 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/mod_filter.html +12 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/notice.html +9 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/online_now.html +13 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/online_now_body.html +47 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/pagination.html +16 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/pilot_fate.html +6 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/results_region.html +9 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/role_toggle.html +10 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/sort_th.html +10 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/stat_mark.html +9 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/stat_mark_note.html +5 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/stat_tile.html +12 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/tour_absent.html +11 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/tour_filter.html +13 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/tour_next.html +7 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/components/tour_select.html +23 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/home.html +109 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/home_activity.html +10 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/home_feature.html +17 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/leaderboards/home_block.html +38 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/leaderboards/ironman_running.html +26 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/leaderboards/list.html +65 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/leaderboards/table.html +105 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/missions/_player.html +7 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/missions/_rows.html +20 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/missions/detail.html +136 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/missions/list.html +44 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/_killboard_rows.html +10 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/_type_killboard.html +40 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/achievements.html +40 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail.html +59 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_achievements.html +20 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_air_section.html +31 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_air_split.html +8 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_air_tiles.html +14 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_aircraft.html +44 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_aircraft_build.html +16 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_charts.html +12 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_ground.html +29 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_ground_scores.html +13 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_ground_section.html +17 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_ground_tiles.html +17 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_header.html +26 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_killboard.html +34 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_nav.html +13 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_overall.html +15 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_pve.html +50 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_ratios.html +16 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_recent.html +40 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_scores.html +11 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_shame.html +17 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_star_tile.html +13 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_streaks.html +26 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_tiles.html +35 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_totals.html +16 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/detail_type_killboard.html +13 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/killboard.html +49 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/search.html +25 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/search_table.html +36 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/streak_runs.html +57 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/players/streaks.html +51 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/setup.html +136 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/setup_done.html +48 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/setup_gate.html +32 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/sorties/all.html +50 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/sorties/detail.html +32 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/sorties/list.html +54 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/sorties/parts/aircraft_cell.html +5 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/sorties/parts/all_row.html +16 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/sorties/parts/ammo.html +72 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/sorties/parts/damage.html +20 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/sorties/parts/damage_table.html +28 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/sorties/parts/header.html +44 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/sorties/parts/kill_table.html +17 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/sorties/parts/killed_by.html +31 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/sorties/parts/kills.html +51 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/sorties/parts/list_row.html +18 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/sorties/parts/medals.html +16 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/sorties/parts/meta.html +15 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/sorties/parts/notices.html +20 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/sorties/parts/summary.html +39 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/sorties/parts/timeline.html +11 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/sorties/parts/timeline_table.html +30 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/sorties/parts/who.html +9 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks/styleguide.html +251 -0
- il2ks-0.1.0/src/il2ks/web/templates/il2ks_admin/theme_editor.html +22 -0
- il2ks-0.1.0/src/il2ks/web/templatetags/il2ks.py +884 -0
- il2ks-0.1.0/src/il2ks/web/templatetags/il2ks_achievements.py +85 -0
- il2ks-0.1.0/src/il2ks/web/templatetags/il2ks_boards.py +71 -0
- il2ks-0.1.0/src/il2ks/web/templatetags/il2ks_live.py +39 -0
- il2ks-0.1.0/src/il2ks/web/templatetags/il2ks_sorties.py +25 -0
- il2ks-0.1.0/src/il2ks/web/theme.py +384 -0
- il2ks-0.1.0/src/il2ks/web/throttle.py +76 -0
- il2ks-0.1.0/src/il2ks/web/urls.py +48 -0
- il2ks-0.1.0/src/il2ks/web/views/__init__.py +1 -0
- il2ks-0.1.0/src/il2ks/web/views/achievements.py +161 -0
- il2ks-0.1.0/src/il2ks/web/views/aircraft.py +357 -0
- il2ks-0.1.0/src/il2ks/web/views/boards.py +123 -0
- il2ks-0.1.0/src/il2ks/web/views/language.py +37 -0
- il2ks-0.1.0/src/il2ks/web/views/leaderboards.py +168 -0
- il2ks-0.1.0/src/il2ks/web/views/live.py +34 -0
- il2ks-0.1.0/src/il2ks/web/views/missions.py +159 -0
- il2ks-0.1.0/src/il2ks/web/views/players.py +162 -0
- il2ks-0.1.0/src/il2ks/web/views/setup.py +252 -0
- il2ks-0.1.0/src/il2ks/web/views/sorties.py +240 -0
- il2ks-0.1.0/src/il2ks/web/views/sprite.py +25 -0
- il2ks-0.1.0/src/il2ks/web/views/styleguide.py +152 -0
- il2ks-0.1.0/src/il2ks/wsgi.py +15 -0
- il2ks-0.1.0/tests/__init__.py +0 -0
- il2ks-0.1.0/tests/aircraft_pages.py +18 -0
- il2ks-0.1.0/tests/conftest.py +67 -0
- il2ks-0.1.0/tests/db_canon.py +135 -0
- il2ks-0.1.0/tests/e2e/__init__.py +0 -0
- il2ks-0.1.0/tests/e2e/branding.py +70 -0
- il2ks-0.1.0/tests/e2e/conftest.py +209 -0
- il2ks-0.1.0/tests/e2e/flow_helpers.py +123 -0
- il2ks-0.1.0/tests/e2e/helpers.py +57 -0
- il2ks-0.1.0/tests/e2e/test_accessibility.py +81 -0
- il2ks-0.1.0/tests/e2e/test_board_switcher.py +49 -0
- il2ks-0.1.0/tests/e2e/test_branding_backgrounds.py +184 -0
- il2ks-0.1.0/tests/e2e/test_branding_theme.py +81 -0
- il2ks-0.1.0/tests/e2e/test_column_hints.py +95 -0
- il2ks-0.1.0/tests/e2e/test_columns_picker.py +246 -0
- il2ks-0.1.0/tests/e2e/test_flows.py +265 -0
- il2ks-0.1.0/tests/e2e/test_flows_admin_and_state.py +203 -0
- il2ks-0.1.0/tests/e2e/test_flows_aircraft.py +268 -0
- il2ks-0.1.0/tests/e2e/test_flows_boards.py +204 -0
- il2ks-0.1.0/tests/e2e/test_flows_more.py +459 -0
- il2ks-0.1.0/tests/e2e/test_flows_sorties.py +79 -0
- il2ks-0.1.0/tests/e2e/test_flows_tours.py +54 -0
- il2ks-0.1.0/tests/e2e/test_frontend_performance.py +258 -0
- il2ks-0.1.0/tests/e2e/test_home_feature_image.py +110 -0
- il2ks-0.1.0/tests/e2e/test_keyboard.py +58 -0
- il2ks-0.1.0/tests/e2e/test_language_menu.py +26 -0
- il2ks-0.1.0/tests/e2e/test_localtime.py +83 -0
- il2ks-0.1.0/tests/e2e/test_nav_history_alignment.py +65 -0
- il2ks-0.1.0/tests/e2e/test_nav_layout.py +124 -0
- il2ks-0.1.0/tests/e2e/test_profile_roles.py +50 -0
- il2ks-0.1.0/tests/e2e/test_row_links.py +78 -0
- il2ks-0.1.0/tests/e2e/test_smoke.py +166 -0
- il2ks-0.1.0/tests/e2e/test_visual_qa.py +355 -0
- il2ks-0.1.0/tests/e2e/tweaks.py +38 -0
- il2ks-0.1.0/tests/e2e/world.py +275 -0
- il2ks-0.1.0/tests/factories.py +352 -0
- il2ks-0.1.0/tests/fixtures/__init__.py +0 -0
- il2ks-0.1.0/tests/fixtures/logs/bailout_ejection_stale_wheels.txt.zip +0 -0
- il2ks-0.1.0/tests/fixtures/logs/most_bailouts.txt.zip +0 -0
- il2ks-0.1.0/tests/fixtures/logs/no_mission_end.txt.zip +0 -0
- il2ks-0.1.0/tests/fixtures/logs/two_mission_ends.txt.zip +0 -0
- il2ks-0.1.0/tests/fixtures/logs/typical.txt.zip +0 -0
- il2ks-0.1.0/tests/ingest_fakes.py +144 -0
- il2ks-0.1.0/tests/integration/__init__.py +0 -0
- il2ks-0.1.0/tests/integration/test_accuracy.py +135 -0
- il2ks-0.1.0/tests/integration/test_achievement_config.py +230 -0
- il2ks-0.1.0/tests/integration/test_achievement_variant_names.py +145 -0
- il2ks-0.1.0/tests/integration/test_achievements.py +459 -0
- il2ks-0.1.0/tests/integration/test_achievements_all_time.py +227 -0
- il2ks-0.1.0/tests/integration/test_achievements_rollup.py +106 -0
- il2ks-0.1.0/tests/integration/test_achievements_second_set.py +225 -0
- il2ks-0.1.0/tests/integration/test_admin.py +1015 -0
- il2ks-0.1.0/tests/integration/test_admin_login_security.py +116 -0
- il2ks-0.1.0/tests/integration/test_aggregates.py +147 -0
- il2ks-0.1.0/tests/integration/test_aircraft_mods.py +376 -0
- il2ks-0.1.0/tests/integration/test_aircraft_roles.py +430 -0
- il2ks-0.1.0/tests/integration/test_aircraft_rollup.py +291 -0
- il2ks-0.1.0/tests/integration/test_aircraft_scopes.py +385 -0
- il2ks-0.1.0/tests/integration/test_aircraft_stats.py +462 -0
- il2ks-0.1.0/tests/integration/test_aircraft_tables.py +217 -0
- il2ks-0.1.0/tests/integration/test_aircraft_type_elo.py +206 -0
- il2ks-0.1.0/tests/integration/test_ammo_mixes.py +188 -0
- il2ks-0.1.0/tests/integration/test_ammo_persist.py +224 -0
- il2ks-0.1.0/tests/integration/test_ammo_pve_pages.py +205 -0
- il2ks-0.1.0/tests/integration/test_assist_split.py +66 -0
- il2ks-0.1.0/tests/integration/test_batched_level2.py +501 -0
- il2ks-0.1.0/tests/integration/test_branding_images.py +303 -0
- il2ks-0.1.0/tests/integration/test_builds.py +151 -0
- il2ks-0.1.0/tests/integration/test_caching.py +181 -0
- il2ks-0.1.0/tests/integration/test_caching_revalidation.py +62 -0
- il2ks-0.1.0/tests/integration/test_charts.py +234 -0
- il2ks-0.1.0/tests/integration/test_column_hints.py +111 -0
- il2ks-0.1.0/tests/integration/test_data_version_bumps.py +66 -0
- il2ks-0.1.0/tests/integration/test_db.py +59 -0
- il2ks-0.1.0/tests/integration/test_dbutil.py +150 -0
- il2ks-0.1.0/tests/integration/test_deprecated_filters.py +19 -0
- il2ks-0.1.0/tests/integration/test_dev_bench.py +54 -0
- il2ks-0.1.0/tests/integration/test_doctor_checks.py +473 -0
- il2ks-0.1.0/tests/integration/test_elo_alltime_minimum.py +91 -0
- il2ks-0.1.0/tests/integration/test_end_to_end.py +132 -0
- il2ks-0.1.0/tests/integration/test_feature_image.py +349 -0
- il2ks-0.1.0/tests/integration/test_flight_score.py +167 -0
- il2ks-0.1.0/tests/integration/test_ground_categories.py +116 -0
- il2ks-0.1.0/tests/integration/test_home_tour.py +207 -0
- il2ks-0.1.0/tests/integration/test_icon_sprite.py +102 -0
- il2ks-0.1.0/tests/integration/test_ingest_runner.py +600 -0
- il2ks-0.1.0/tests/integration/test_killboard_streaks.py +305 -0
- il2ks-0.1.0/tests/integration/test_killboard_tours.py +350 -0
- il2ks-0.1.0/tests/integration/test_language.py +301 -0
- il2ks-0.1.0/tests/integration/test_leaderboards.py +439 -0
- il2ks-0.1.0/tests/integration/test_level2_end_to_end.py +153 -0
- il2ks-0.1.0/tests/integration/test_level2_per_tour_order.py +136 -0
- il2ks-0.1.0/tests/integration/test_list_columns.py +516 -0
- il2ks-0.1.0/tests/integration/test_live.py +391 -0
- il2ks-0.1.0/tests/integration/test_live_sorties.py +753 -0
- il2ks-0.1.0/tests/integration/test_live_sorties_web.py +78 -0
- il2ks-0.1.0/tests/integration/test_live_web.py +317 -0
- il2ks-0.1.0/tests/integration/test_local_time_pages.py +21 -0
- il2ks-0.1.0/tests/integration/test_media_view.py +140 -0
- il2ks-0.1.0/tests/integration/test_migrate_aircraft_merge.py +112 -0
- il2ks-0.1.0/tests/integration/test_migrate_catalog_refresh.py +130 -0
- il2ks-0.1.0/tests/integration/test_mission_pages.py +278 -0
- il2ks-0.1.0/tests/integration/test_mission_sortie_table.py +230 -0
- il2ks-0.1.0/tests/integration/test_nav_history.py +76 -0
- il2ks-0.1.0/tests/integration/test_ops_commands.py +620 -0
- il2ks-0.1.0/tests/integration/test_ops_real_process.py +102 -0
- il2ks-0.1.0/tests/integration/test_override_banner.py +108 -0
- il2ks-0.1.0/tests/integration/test_pagination_sizes.py +116 -0
- il2ks-0.1.0/tests/integration/test_persist.py +321 -0
- il2ks-0.1.0/tests/integration/test_persist_combat_fields.py +83 -0
- il2ks-0.1.0/tests/integration/test_persist_rules.py +348 -0
- il2ks-0.1.0/tests/integration/test_pilot_fate_pages.py +123 -0
- il2ks-0.1.0/tests/integration/test_player_pages.py +555 -0
- il2ks-0.1.0/tests/integration/test_player_rollup.py +268 -0
- il2ks-0.1.0/tests/integration/test_pve_breakdown.py +107 -0
- il2ks-0.1.0/tests/integration/test_quips.py +249 -0
- il2ks-0.1.0/tests/integration/test_ratings.py +260 -0
- il2ks-0.1.0/tests/integration/test_reprocess_requests.py +311 -0
- il2ks-0.1.0/tests/integration/test_reprocess_span.py +133 -0
- il2ks-0.1.0/tests/integration/test_rollup.py +94 -0
- il2ks-0.1.0/tests/integration/test_row_links_and_flavor.py +105 -0
- il2ks-0.1.0/tests/integration/test_rule_settings.py +342 -0
- il2ks-0.1.0/tests/integration/test_rules_review12.py +264 -0
- il2ks-0.1.0/tests/integration/test_scores.py +200 -0
- il2ks-0.1.0/tests/integration/test_setup_page.py +515 -0
- il2ks-0.1.0/tests/integration/test_shame_quip.py +103 -0
- il2ks-0.1.0/tests/integration/test_skill_boards.py +261 -0
- il2ks-0.1.0/tests/integration/test_sortie_list.py +213 -0
- il2ks-0.1.0/tests/integration/test_sortie_pages.py +745 -0
- il2ks-0.1.0/tests/integration/test_sortie_tour.py +90 -0
- il2ks-0.1.0/tests/integration/test_sqlite_settings.py +84 -0
- il2ks-0.1.0/tests/integration/test_stat_marks.py +459 -0
- il2ks-0.1.0/tests/integration/test_static_minify.py +103 -0
- il2ks-0.1.0/tests/integration/test_streak_runs.py +262 -0
- il2ks-0.1.0/tests/integration/test_streak_tracks.py +466 -0
- il2ks-0.1.0/tests/integration/test_tour_clean_slate.py +185 -0
- il2ks-0.1.0/tests/integration/test_tour_pages.py +317 -0
- il2ks-0.1.0/tests/integration/test_tour_ratings.py +230 -0
- il2ks-0.1.0/tests/integration/test_tour_robustness.py +317 -0
- il2ks-0.1.0/tests/integration/test_tours.py +828 -0
- il2ks-0.1.0/tests/integration/test_tours_decisive.py +283 -0
- il2ks-0.1.0/tests/integration/test_tours_decisive_admin.py +71 -0
- il2ks-0.1.0/tests/integration/test_tours_review11.py +246 -0
- il2ks-0.1.0/tests/integration/test_type_killboards.py +362 -0
- il2ks-0.1.0/tests/integration/test_upgrade_costs.py +92 -0
- il2ks-0.1.0/tests/integration/test_views.py +12 -0
- il2ks-0.1.0/tests/integration/test_weapon_mod_names.py +58 -0
- il2ks-0.1.0/tests/integration/test_web_alongside_ingest.py +104 -0
- il2ks-0.1.0/tests/integration/test_web_foundation.py +356 -0
- il2ks-0.1.0/tests/legacy_aircraft_alltime.py +705 -0
- il2ks-0.1.0/tests/level1_oracle.py +225 -0
- il2ks-0.1.0/tests/live_helpers.py +65 -0
- il2ks-0.1.0/tests/ops_helpers.py +105 -0
- il2ks-0.1.0/tests/perf/conftest.py +37 -0
- il2ks-0.1.0/tests/perf/pages.py +57 -0
- il2ks-0.1.0/tests/perf/plan_variants.py +262 -0
- il2ks-0.1.0/tests/perf/query_plans.py +323 -0
- il2ks-0.1.0/tests/perf/seed.py +137 -0
- il2ks-0.1.0/tests/perf/test_query_plans.py +174 -0
- il2ks-0.1.0/tests/perf/test_server_timing.py +103 -0
- il2ks-0.1.0/tests/simple_reads.py +43 -0
- il2ks-0.1.0/tests/sortie_tours.py +17 -0
- il2ks-0.1.0/tests/unit/__init__.py +0 -0
- il2ks-0.1.0/tests/unit/catalog/__init__.py +0 -0
- il2ks-0.1.0/tests/unit/catalog/test_ammo_names.py +107 -0
- il2ks-0.1.0/tests/unit/catalog/test_data_files.py +139 -0
- il2ks-0.1.0/tests/unit/catalog/test_lookup.py +247 -0
- il2ks-0.1.0/tests/unit/catalog/test_object_names.py +130 -0
- il2ks-0.1.0/tests/unit/catalog/test_ordnance.py +109 -0
- il2ks-0.1.0/tests/unit/catalog/test_payload_lookup.py +61 -0
- il2ks-0.1.0/tests/unit/catalog/test_sample_coverage.py +72 -0
- il2ks-0.1.0/tests/unit/catalog/test_significant_mods.py +43 -0
- il2ks-0.1.0/tests/unit/catalog/test_weapon_mod_names.py +73 -0
- il2ks-0.1.0/tests/unit/catalog/test_weapon_mods.py +62 -0
- il2ks-0.1.0/tests/unit/ingest/__init__.py +0 -0
- il2ks-0.1.0/tests/unit/ingest/test_archive.py +165 -0
- il2ks-0.1.0/tests/unit/ingest/test_discover.py +178 -0
- il2ks-0.1.0/tests/unit/ingest/test_lock.py +107 -0
- il2ks-0.1.0/tests/unit/ingest/test_worker.py +23 -0
- il2ks-0.1.0/tests/unit/logparse/__init__.py +0 -0
- il2ks-0.1.0/tests/unit/logparse/test_event_immutability.py +14 -0
- il2ks-0.1.0/tests/unit/logparse/test_explosion_burst.py +187 -0
- il2ks-0.1.0/tests/unit/logparse/test_fast_path.py +73 -0
- il2ks-0.1.0/tests/unit/logparse/test_files.py +147 -0
- il2ks-0.1.0/tests/unit/logparse/test_parser.py +599 -0
- il2ks-0.1.0/tests/unit/logparse/test_real_logs.py +66 -0
- il2ks-0.1.0/tests/unit/logparse/test_tail.py +95 -0
- il2ks-0.1.0/tests/unit/ops/__init__.py +0 -0
- il2ks-0.1.0/tests/unit/ops/test_backup.py +529 -0
- il2ks-0.1.0/tests/unit/ops/test_patch_config.py +63 -0
- il2ks-0.1.0/tests/unit/ops/test_setup_validation.py +132 -0
- il2ks-0.1.0/tests/unit/ops/test_template_and_detect.py +198 -0
- il2ks-0.1.0/tests/unit/ratings/__init__.py +0 -0
- il2ks-0.1.0/tests/unit/ratings/test_elo.py +134 -0
- il2ks-0.1.0/tests/unit/ratings/test_score.py +188 -0
- il2ks-0.1.0/tests/unit/replay/__init__.py +0 -0
- il2ks-0.1.0/tests/unit/replay/builder.py +293 -0
- il2ks-0.1.0/tests/unit/replay/test_accuracy.py +87 -0
- il2ks-0.1.0/tests/unit/replay/test_achievement_facts.py +107 -0
- il2ks-0.1.0/tests/unit/replay/test_ammo.py +492 -0
- il2ks-0.1.0/tests/unit/replay/test_ammo_left_after_loss.py +89 -0
- il2ks-0.1.0/tests/unit/replay/test_attack.py +377 -0
- il2ks-0.1.0/tests/unit/replay/test_attack_samples.py +34 -0
- il2ks-0.1.0/tests/unit/replay/test_bailout_v3.py +193 -0
- il2ks-0.1.0/tests/unit/replay/test_capture.py +63 -0
- il2ks-0.1.0/tests/unit/replay/test_cleanup_damage.py +56 -0
- il2ks-0.1.0/tests/unit/replay/test_damage_legs.py +273 -0
- il2ks-0.1.0/tests/unit/replay/test_friendly_fire.py +127 -0
- il2ks-0.1.0/tests/unit/replay/test_ground_categories.py +69 -0
- il2ks-0.1.0/tests/unit/replay/test_ground_losses.py +376 -0
- il2ks-0.1.0/tests/unit/replay/test_gunners.py +273 -0
- il2ks-0.1.0/tests/unit/replay/test_interception.py +95 -0
- il2ks-0.1.0/tests/unit/replay/test_live.py +107 -0
- il2ks-0.1.0/tests/unit/replay/test_mission_result.py +56 -0
- il2ks-0.1.0/tests/unit/replay/test_outcomes.py +440 -0
- il2ks-0.1.0/tests/unit/replay/test_parachute_deaths.py +50 -0
- il2ks-0.1.0/tests/unit/replay/test_pilot_fate.py +367 -0
- il2ks-0.1.0/tests/unit/replay/test_pilot_final_pos.py +132 -0
- il2ks-0.1.0/tests/unit/replay/test_pilot_health.py +55 -0
- il2ks-0.1.0/tests/unit/replay/test_post_end_window.py +143 -0
- il2ks-0.1.0/tests/unit/replay/test_pve_breakdown.py +129 -0
- il2ks-0.1.0/tests/unit/replay/test_rams.py +186 -0
- il2ks-0.1.0/tests/unit/replay/test_reset_destruction.py +77 -0
- il2ks-0.1.0/tests/unit/replay/test_resupply.py +52 -0
- il2ks-0.1.0/tests/unit/replay/test_sample_distributions.py +45 -0
- il2ks-0.1.0/tests/unit/replay/test_streaming.py +101 -0
- il2ks-0.1.0/tests/unit/replay/test_timeline_hits.py +200 -0
- il2ks-0.1.0/tests/unit/test_achievements.py +345 -0
- il2ks-0.1.0/tests/unit/test_achievements_all_time.py +98 -0
- il2ks-0.1.0/tests/unit/test_achievements_second_set.py +238 -0
- il2ks-0.1.0/tests/unit/test_anonymize.py +65 -0
- il2ks-0.1.0/tests/unit/test_asset_inventory.py +37 -0
- il2ks-0.1.0/tests/unit/test_bootid.py +27 -0
- il2ks-0.1.0/tests/unit/test_branding_images.py +155 -0
- il2ks-0.1.0/tests/unit/test_caddy.py +214 -0
- il2ks-0.1.0/tests/unit/test_catalog_payloads.py +45 -0
- il2ks-0.1.0/tests/unit/test_charts.py +157 -0
- il2ks-0.1.0/tests/unit/test_claude_hooks.py +161 -0
- il2ks-0.1.0/tests/unit/test_cli.py +292 -0
- il2ks-0.1.0/tests/unit/test_config.py +270 -0
- il2ks-0.1.0/tests/unit/test_config_rules.py +52 -0
- il2ks-0.1.0/tests/unit/test_config_serving.py +126 -0
- il2ks-0.1.0/tests/unit/test_config_template.py +134 -0
- il2ks-0.1.0/tests/unit/test_config_tours.py +62 -0
- il2ks-0.1.0/tests/unit/test_custom.py +482 -0
- il2ks-0.1.0/tests/unit/test_dev_check.py +132 -0
- il2ks-0.1.0/tests/unit/test_djsettings.py +136 -0
- il2ks-0.1.0/tests/unit/test_flavor.py +325 -0
- il2ks-0.1.0/tests/unit/test_fonts.py +272 -0
- il2ks-0.1.0/tests/unit/test_i18n_templates.py +44 -0
- il2ks-0.1.0/tests/unit/test_icon_files.py +74 -0
- il2ks-0.1.0/tests/unit/test_local_time.py +48 -0
- il2ks-0.1.0/tests/unit/test_logo.py +232 -0
- il2ks-0.1.0/tests/unit/test_logsetup.py +180 -0
- il2ks-0.1.0/tests/unit/test_migration_guards.py +180 -0
- il2ks-0.1.0/tests/unit/test_packaging.py +105 -0
- il2ks-0.1.0/tests/unit/test_pilot_fate_display.py +47 -0
- il2ks-0.1.0/tests/unit/test_quips.py +114 -0
- il2ks-0.1.0/tests/unit/test_release_workflow.py +16 -0
- il2ks-0.1.0/tests/unit/test_rule_settings.py +178 -0
- il2ks-0.1.0/tests/unit/test_secret.py +59 -0
- il2ks-0.1.0/tests/unit/test_service.py +217 -0
- il2ks-0.1.0/tests/unit/test_serving_checks.py +255 -0
- il2ks-0.1.0/tests/unit/test_serving_commands.py +899 -0
- il2ks-0.1.0/tests/unit/test_setup_token.py +126 -0
- il2ks-0.1.0/tests/unit/test_sortie_view.py +127 -0
- il2ks-0.1.0/tests/unit/test_stat_marks.py +347 -0
- il2ks-0.1.0/tests/unit/test_streaks_core.py +227 -0
- il2ks-0.1.0/tests/unit/test_supervisor.py +291 -0
- il2ks-0.1.0/tests/unit/test_svg_symbol.py +95 -0
- il2ks-0.1.0/tests/unit/test_template_compile.py +50 -0
- il2ks-0.1.0/tests/unit/test_template_versions.py +371 -0
- il2ks-0.1.0/tests/unit/test_theme.py +263 -0
- il2ks-0.1.0/tests/unit/test_timeutil.py +99 -0
- il2ks-0.1.0/tests/unit/test_tours_core.py +153 -0
- il2ks-0.1.0/tests/unit/test_translations.py +293 -0
- il2ks-0.1.0/tests/unit/test_web_display.py +136 -0
- il2ks-0.1.0/tests/unit/test_web_missions_display.py +140 -0
- il2ks-0.1.0/tests/unit/test_windows_packaging.py +294 -0
- il2ks-0.1.0/uv.lock +2090 -0
- il2ks-0.1.0/vulture_whitelist.py +301 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# The image only needs pyproject.toml, uv.lock, README.md, LICENSE, NOTICE, src/ and docker/docker-entrypoint.sh.
|
|
2
|
+
# Never send the game's real logs or local state to the daemon.
|
|
3
|
+
*
|
|
4
|
+
!pyproject.toml
|
|
5
|
+
!uv.lock
|
|
6
|
+
!README.md
|
|
7
|
+
!LICENSE
|
|
8
|
+
!NOTICE
|
|
9
|
+
!src/**
|
|
10
|
+
!docker/docker-entrypoint.sh
|
|
11
|
+
**/__pycache__
|
|
12
|
+
**/*.pyc
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Runs an Inno Setup installer silently with a timeout. It always prints the installer log, the il2ks logs and the process tree
|
|
2
|
+
# afterwards; on a timeout it also kills the installer, so a hang shows where it hangs instead of eating the job's time limit.
|
|
3
|
+
# Usage: run-installer.ps1 -Exe <path> -LogFile <setup log> -Arguments <installer switches...> [-TimeoutSeconds 900]
|
|
4
|
+
param(
|
|
5
|
+
[Parameter(Mandatory)] [string] $Exe,
|
|
6
|
+
[Parameter(Mandatory)] [string] $LogFile,
|
|
7
|
+
[Parameter(Mandatory)] [string[]] $Arguments,
|
|
8
|
+
[int] $TimeoutSeconds = 900
|
|
9
|
+
)
|
|
10
|
+
$ErrorActionPreference = 'Continue'
|
|
11
|
+
|
|
12
|
+
function Show-Diagnostics {
|
|
13
|
+
Write-Host "::group::installer log ($LogFile)"
|
|
14
|
+
if (Test-Path $LogFile) { Get-Content $LogFile -Tail 150 } else { Write-Host "(no log file)" }
|
|
15
|
+
Write-Host "::endgroup::"
|
|
16
|
+
Write-Host "::group::il2ks logs in ProgramData"
|
|
17
|
+
Get-ChildItem "$env:ProgramData\il2ks" -Recurse -File -ErrorAction SilentlyContinue |
|
|
18
|
+
Where-Object { $_.FullName -like '*\logs\*' } |
|
|
19
|
+
ForEach-Object { "== $($_.FullName)"; Get-Content $_.FullName -Tail 30 }
|
|
20
|
+
Write-Host "::endgroup::"
|
|
21
|
+
Write-Host "::group::process tree"
|
|
22
|
+
Get-CimInstance Win32_Process |
|
|
23
|
+
Where-Object { $_.Name -match 'il2ks|python|cmd|icacls|sc\.exe|netsh|caddy' } |
|
|
24
|
+
Select-Object ProcessId, ParentProcessId, Name, CommandLine | Format-List | Out-String -Width 250
|
|
25
|
+
Write-Host "::endgroup::"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
$arglist = ($Arguments | ForEach-Object { if ($_ -match '\s') { '"' + $_ + '"' } else { $_ } }) -join ' '
|
|
29
|
+
# No -Wait: that also waits for every process the installer started, and has no timeout.
|
|
30
|
+
$p = Start-Process -FilePath $Exe -ArgumentList $arglist -PassThru
|
|
31
|
+
if (-not $p.WaitForExit($TimeoutSeconds * 1000)) {
|
|
32
|
+
Write-Host "::error::the installer did not finish within $TimeoutSeconds seconds"
|
|
33
|
+
Show-Diagnostics
|
|
34
|
+
Get-CimInstance Win32_Process | Where-Object { $_.Name -like 'il2ks-setup*' } |
|
|
35
|
+
ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }
|
|
36
|
+
throw "installer timed out"
|
|
37
|
+
}
|
|
38
|
+
$p.WaitForExit()
|
|
39
|
+
Show-Diagnostics
|
|
40
|
+
if ($p.ExitCode -ne 0) { throw "installer exit code $($p.ExitCode)" }
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
lint:
|
|
10
|
+
# The same command agents and pre-commit run (`il2ks dev check`), minus the tests (the jobs below run those):
|
|
11
|
+
# ruff, format, pyright, import-linter, vulture, makemigrations --check, migration immutability / single leaf,
|
|
12
|
+
# bump-templates --check, translations check. Full history: the migration guard compares with origin/main.
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v7
|
|
16
|
+
with:
|
|
17
|
+
fetch-depth: 0
|
|
18
|
+
- uses: astral-sh/setup-uv@v10.2.0
|
|
19
|
+
- run: uv sync --locked
|
|
20
|
+
- run: uv run il2ks dev check --no-tests --verbose
|
|
21
|
+
|
|
22
|
+
test-sqlite:
|
|
23
|
+
# SQLite is the default test database (TD-19). Windows is the main target platform.
|
|
24
|
+
strategy:
|
|
25
|
+
fail-fast: false
|
|
26
|
+
matrix:
|
|
27
|
+
os: [ubuntu-latest, windows-latest]
|
|
28
|
+
runs-on: ${{ matrix.os }}
|
|
29
|
+
steps:
|
|
30
|
+
- uses: actions/checkout@v7
|
|
31
|
+
- uses: astral-sh/setup-uv@v10.2.0
|
|
32
|
+
- run: uv sync --locked
|
|
33
|
+
- run: uv run pytest -m "not perf" # the budgets of tests/perf have their own job (test-perf)
|
|
34
|
+
|
|
35
|
+
test-postgres:
|
|
36
|
+
# Postgres is dev-side only: one extra job keeps a future switch cheap (TD-04, TD-19).
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
services:
|
|
39
|
+
postgres:
|
|
40
|
+
image: postgres:17
|
|
41
|
+
env:
|
|
42
|
+
POSTGRES_USER: il2ks
|
|
43
|
+
POSTGRES_PASSWORD: il2ks
|
|
44
|
+
POSTGRES_DB: il2ks
|
|
45
|
+
ports: ["5432:5432"]
|
|
46
|
+
options: >-
|
|
47
|
+
--health-cmd "pg_isready -U il2ks" --health-interval 5s --health-timeout 5s --health-retries 10
|
|
48
|
+
env:
|
|
49
|
+
IL2KS_TEST_DB: postgres
|
|
50
|
+
steps:
|
|
51
|
+
- uses: actions/checkout@v7
|
|
52
|
+
- uses: astral-sh/setup-uv@v10.2.0
|
|
53
|
+
- run: uv sync --locked
|
|
54
|
+
- run: uv run pytest -m "not perf" # the budgets of tests/perf have their own job (test-perf)
|
|
55
|
+
|
|
56
|
+
test-perf:
|
|
57
|
+
# Query and time budgets of every public page over a seeded world (tests/perf, marker `perf`; OQ-97). Kept out of
|
|
58
|
+
# the functional jobs so a slow runner never fails them. SQLite first (what ships), then the Postgres service:
|
|
59
|
+
# Postgres plans queries differently and is where a slow query shows up.
|
|
60
|
+
runs-on: ubuntu-latest
|
|
61
|
+
services:
|
|
62
|
+
postgres:
|
|
63
|
+
image: postgres:17
|
|
64
|
+
env:
|
|
65
|
+
POSTGRES_USER: il2ks
|
|
66
|
+
POSTGRES_PASSWORD: il2ks
|
|
67
|
+
POSTGRES_DB: il2ks
|
|
68
|
+
ports: ["5432:5432"]
|
|
69
|
+
options: >-
|
|
70
|
+
--health-cmd "pg_isready -U il2ks" --health-interval 5s --health-timeout 5s --health-retries 10
|
|
71
|
+
steps:
|
|
72
|
+
- uses: actions/checkout@v7
|
|
73
|
+
- uses: astral-sh/setup-uv@v10.2.0
|
|
74
|
+
- run: uv sync --locked
|
|
75
|
+
- run: uv run pytest -m perf -n 0
|
|
76
|
+
- run: uv run pytest -m perf -n 0
|
|
77
|
+
env:
|
|
78
|
+
IL2KS_TEST_DB: postgres
|
|
79
|
+
|
|
80
|
+
test-e2e:
|
|
81
|
+
# Browser tests (doc 08): the real app in a child process, driven by Chromium through Playwright. Opt-in locally
|
|
82
|
+
# (IL2KS_TEST_E2E=1); always on here. Traces and screenshots of failures are kept as an artifact.
|
|
83
|
+
runs-on: ubuntu-24.04 # Playwright's --with-deps apt step lags behind new Ubuntu releases (ubuntu-latest moves to 26 on 2026-10-19)
|
|
84
|
+
env:
|
|
85
|
+
IL2KS_TEST_E2E: "1"
|
|
86
|
+
steps:
|
|
87
|
+
- uses: actions/checkout@v7
|
|
88
|
+
- uses: astral-sh/setup-uv@v10.2.0
|
|
89
|
+
- run: uv sync --locked
|
|
90
|
+
- run: uv run playwright install --with-deps chromium
|
|
91
|
+
- run: >-
|
|
92
|
+
uv run pytest -m e2e --basetemp=e2e-tmp --output=test-results
|
|
93
|
+
--tracing=retain-on-failure --screenshot=only-on-failure
|
|
94
|
+
- uses: actions/upload-artifact@v7
|
|
95
|
+
if: failure()
|
|
96
|
+
with:
|
|
97
|
+
name: e2e-failure-${{ github.run_id }}
|
|
98
|
+
path: |
|
|
99
|
+
test-results/
|
|
100
|
+
e2e-tmp/**/server.log
|
|
101
|
+
if-no-files-found: ignore
|
|
102
|
+
retention-days: 14
|
|
103
|
+
|
|
104
|
+
package:
|
|
105
|
+
# The wheel must carry templates, static files, catalog data, the example config and the migrations (PyPI path).
|
|
106
|
+
runs-on: ubuntu-latest
|
|
107
|
+
steps:
|
|
108
|
+
- uses: actions/checkout@v7
|
|
109
|
+
- uses: astral-sh/setup-uv@v10.2.0
|
|
110
|
+
- run: uv sync --locked
|
|
111
|
+
- run: uv run pytest tests/unit/test_packaging.py
|
|
112
|
+
env:
|
|
113
|
+
IL2KS_TEST_BUILD: "1"
|
|
114
|
+
|
|
115
|
+
docker:
|
|
116
|
+
# The image of docs/install-docker.md (doc 07 option A): build it (nothing is pushed) and smoke-test it.
|
|
117
|
+
runs-on: ubuntu-latest
|
|
118
|
+
steps:
|
|
119
|
+
- uses: actions/checkout@v7
|
|
120
|
+
- run: docker build -f docker/Dockerfile -t il2ks:ci .
|
|
121
|
+
- run: docker compose -f docker/compose.yaml config --quiet
|
|
122
|
+
env:
|
|
123
|
+
IL2KS_SERVER_TIMEZONE: UTC
|
|
124
|
+
IL2KS_LOGS_HOST_DIR: /tmp
|
|
125
|
+
- run: docker/smoke-test.sh il2ks:ci
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: Load test
|
|
2
|
+
|
|
3
|
+
# Manual only (Actions tab -> Load test -> Run workflow): load numbers on a shared runner are too noisy to gate a
|
|
4
|
+
# commit on. Seeds a scratch database, runs Locust against `il2ks web --dev`, uploads the report (docs/performance-testing.md).
|
|
5
|
+
on:
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
inputs:
|
|
8
|
+
users:
|
|
9
|
+
description: Concurrent users
|
|
10
|
+
default: "20"
|
|
11
|
+
run_time:
|
|
12
|
+
description: Run time (Locust syntax, e.g. 60s or 3m)
|
|
13
|
+
default: "60s"
|
|
14
|
+
missions:
|
|
15
|
+
description: Missions to seed
|
|
16
|
+
default: "60"
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
loadtest:
|
|
20
|
+
runs-on: ubuntu-24.04
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v7
|
|
23
|
+
- uses: astral-sh/setup-uv@v10.2.0
|
|
24
|
+
- run: uv sync --locked
|
|
25
|
+
- name: Seed, serve and load the site
|
|
26
|
+
run: >-
|
|
27
|
+
uv run python loadtest/run.py
|
|
28
|
+
-u "${{ inputs.users }}" -t "${{ inputs.run_time }}" --missions "${{ inputs.missions }}"
|
|
29
|
+
--html loadtest-report.html | tee loadtest-report.md
|
|
30
|
+
- uses: actions/upload-artifact@v7
|
|
31
|
+
if: always()
|
|
32
|
+
with:
|
|
33
|
+
name: loadtest-${{ github.run_id }}
|
|
34
|
+
path: |
|
|
35
|
+
loadtest-report.html
|
|
36
|
+
loadtest-report.md
|
|
37
|
+
if-no-files-found: ignore
|
|
38
|
+
retention-days: 30
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Pushing a tag like v0.1.0 builds il2ks, proves the wheel works in a clean environment on Linux and Windows, and
|
|
4
|
+
# publishes it to PyPI with trusted publishing (no API token stored anywhere).
|
|
5
|
+
#
|
|
6
|
+
# One-time setup on pypi.org: Your projects -> il2ks -> Publishing -> add a trusted publisher
|
|
7
|
+
# owner: FGlazov repository: il2_korea_stats workflow: release.yml environment: pypi
|
|
8
|
+
# (for the very first release, add it as a "pending publisher" under Your account -> Publishing).
|
|
9
|
+
# And in GitHub: Settings -> Environments -> New environment "pypi" (optionally require a reviewer there).
|
|
10
|
+
#
|
|
11
|
+
# Release steps: bump __version__ in src/il2ks/__init__.py (the only place), commit, `git tag v<version>`, push the tag.
|
|
12
|
+
|
|
13
|
+
on:
|
|
14
|
+
push:
|
|
15
|
+
tags: ["v*"]
|
|
16
|
+
|
|
17
|
+
permissions:
|
|
18
|
+
contents: read
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
build:
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v7
|
|
25
|
+
- uses: astral-sh/setup-uv@v10.2.0
|
|
26
|
+
- run: uv sync --locked
|
|
27
|
+
|
|
28
|
+
- name: The tag must match the package version
|
|
29
|
+
run: |
|
|
30
|
+
version="$(uv run python -c 'import il2ks; print(il2ks.__version__)')"
|
|
31
|
+
if [ "v${version}" != "${GITHUB_REF_NAME}" ]; then
|
|
32
|
+
echo "Tag ${GITHUB_REF_NAME} does not match il2ks.__version__ ${version}" >&2
|
|
33
|
+
exit 1
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
- name: Template versions count again after the first release (TD-25)
|
|
37
|
+
run: |
|
|
38
|
+
done="$(uv run python -c 'from il2ks.serving.templateversions import FIRST_RELEASE_DONE; print(FIRST_RELEASE_DONE)')"
|
|
39
|
+
case "${GITHUB_REF_NAME}" in *a[0-9]*|*b[0-9]*|*rc[0-9]*) echo "pre-release tag: the switch may stay off"; exit 0;; esac
|
|
40
|
+
if [ "${done}" != "True" ]; then
|
|
41
|
+
echo "FIRST_RELEASE_DONE is still False in serving/templateversions.py: flip it before tagging (docs/releasing.md)" >&2
|
|
42
|
+
exit 1
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
- name: Tests, including the wheel contents check
|
|
46
|
+
run: uv run pytest -q
|
|
47
|
+
env:
|
|
48
|
+
IL2KS_TEST_BUILD: "1"
|
|
49
|
+
|
|
50
|
+
- name: Build wheel and sdist
|
|
51
|
+
run: uv build
|
|
52
|
+
|
|
53
|
+
- uses: actions/upload-artifact@v7
|
|
54
|
+
with:
|
|
55
|
+
name: dist
|
|
56
|
+
path: dist/
|
|
57
|
+
if-no-files-found: error
|
|
58
|
+
|
|
59
|
+
smoke:
|
|
60
|
+
# Install the built wheel into a fresh virtual environment, away from the source tree, and make it do real work.
|
|
61
|
+
needs: build
|
|
62
|
+
strategy:
|
|
63
|
+
fail-fast: true
|
|
64
|
+
matrix:
|
|
65
|
+
os: [ubuntu-latest, windows-latest]
|
|
66
|
+
runs-on: ${{ matrix.os }}
|
|
67
|
+
defaults:
|
|
68
|
+
run:
|
|
69
|
+
shell: bash
|
|
70
|
+
steps:
|
|
71
|
+
- uses: astral-sh/setup-uv@v10.2.0
|
|
72
|
+
- uses: actions/download-artifact@v8
|
|
73
|
+
with:
|
|
74
|
+
name: dist
|
|
75
|
+
path: dist
|
|
76
|
+
|
|
77
|
+
- name: Install the wheel in a clean venv
|
|
78
|
+
run: |
|
|
79
|
+
uv venv --python 3.13 smoke-venv
|
|
80
|
+
if [ "$RUNNER_OS" = "Windows" ]; then BIN=smoke-venv/Scripts; else BIN=smoke-venv/bin; fi
|
|
81
|
+
echo "BIN=$PWD/$BIN" >> "$GITHUB_ENV"
|
|
82
|
+
uv pip install --python smoke-venv dist/*.whl # the folder: `Scripts/python` without `.exe` fails on Windows
|
|
83
|
+
|
|
84
|
+
- name: il2ks --help and --version
|
|
85
|
+
run: |
|
|
86
|
+
"$BIN/il2ks" --help
|
|
87
|
+
"$BIN/il2ks" --version
|
|
88
|
+
|
|
89
|
+
- name: Smoke test
|
|
90
|
+
env:
|
|
91
|
+
IL2KS_DATA_DIR: ${{ github.workspace }}/smoke-data
|
|
92
|
+
run: |
|
|
93
|
+
"$BIN/il2ks" manage migrate --noinput
|
|
94
|
+
"$BIN/il2ks" custom list --builtin | grep "templates/il2ks/base.html" > /dev/null
|
|
95
|
+
"$BIN/il2ks" caddyfile | grep "reverse_proxy 127.0.0.1:8000" > /dev/null
|
|
96
|
+
"$BIN/il2ks" service systemd | grep "ExecStart=" > /dev/null
|
|
97
|
+
"$BIN/il2ks" web --dev --port 18000 > web.log 2>&1 &
|
|
98
|
+
ok=0
|
|
99
|
+
for i in $(seq 1 40); do
|
|
100
|
+
if curl -fsS http://127.0.0.1:18000/ > /dev/null; then ok=1; break; fi
|
|
101
|
+
sleep 1
|
|
102
|
+
done
|
|
103
|
+
cat web.log
|
|
104
|
+
[ "$ok" = "1" ] || { echo "the site did not answer" >&2; exit 1; }
|
|
105
|
+
curl -fsS http://127.0.0.1:18000/admin/login/ > /dev/null
|
|
106
|
+
if [ "$RUNNER_OS" = "Linux" ]; then pkill -f "il2ks web" || true; fi
|
|
107
|
+
|
|
108
|
+
publish:
|
|
109
|
+
needs: smoke
|
|
110
|
+
runs-on: ubuntu-latest
|
|
111
|
+
environment: pypi
|
|
112
|
+
permissions:
|
|
113
|
+
id-token: write # trusted publishing
|
|
114
|
+
steps:
|
|
115
|
+
- uses: actions/download-artifact@v8
|
|
116
|
+
with:
|
|
117
|
+
name: dist
|
|
118
|
+
path: dist
|
|
119
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
name: Windows installer
|
|
2
|
+
|
|
3
|
+
# Builds dist/il2ks-setup-<version>.exe (packaging/windows, doc 07 option B), smoke-tests it, and on a version tag attaches it
|
|
4
|
+
# to the GitHub release. Not run on every push: it downloads about 90 MB of pinned inputs and takes several minutes.
|
|
5
|
+
#
|
|
6
|
+
# - tag v* build + smoke test + release asset (+ the real-service test, which may fail without blocking)
|
|
7
|
+
# - workflow_dispatch build + smoke test, uploaded as a workflow artifact; tick "service_test" for the real-service test
|
|
8
|
+
#
|
|
9
|
+
# The smoke test installs into a temp folder with the service and firewall steps switched off (/NOSERVICE /NOFIREWALL), so it
|
|
10
|
+
# changes nothing outside the runner's disposable VM anyway. The service test installs the real service on that VM.
|
|
11
|
+
|
|
12
|
+
on:
|
|
13
|
+
push:
|
|
14
|
+
tags: ["v*"]
|
|
15
|
+
workflow_dispatch:
|
|
16
|
+
inputs:
|
|
17
|
+
service_test:
|
|
18
|
+
description: "Also install the real Windows service on the runner and check start and graceful stop"
|
|
19
|
+
type: boolean
|
|
20
|
+
default: false
|
|
21
|
+
|
|
22
|
+
permissions:
|
|
23
|
+
contents: read
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
build:
|
|
27
|
+
runs-on: windows-latest
|
|
28
|
+
steps:
|
|
29
|
+
- uses: actions/checkout@v7
|
|
30
|
+
- uses: astral-sh/setup-uv@v10.2.0
|
|
31
|
+
- run: uv sync --locked
|
|
32
|
+
|
|
33
|
+
- name: The tag must match the package version
|
|
34
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
35
|
+
shell: bash
|
|
36
|
+
run: |
|
|
37
|
+
version="$(uv run python -c 'import il2ks; print(il2ks.__version__)')"
|
|
38
|
+
if [ "v${version}" != "${GITHUB_REF_NAME}" ]; then
|
|
39
|
+
echo "Tag ${GITHUB_REF_NAME} does not match il2ks.__version__ ${version}" >&2
|
|
40
|
+
exit 1
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
- name: Build the installer (pinned inputs, SHA-256 checked)
|
|
44
|
+
run: uv run python packaging/windows/build.py
|
|
45
|
+
|
|
46
|
+
- uses: actions/upload-artifact@v7
|
|
47
|
+
with:
|
|
48
|
+
name: il2ks-windows-installer
|
|
49
|
+
path: dist/il2ks-setup-*.exe
|
|
50
|
+
if-no-files-found: error
|
|
51
|
+
|
|
52
|
+
smoke:
|
|
53
|
+
# Install silently into a temp folder, no service, no firewall; run il2ks from the installed copy; uninstall.
|
|
54
|
+
needs: build
|
|
55
|
+
runs-on: windows-latest
|
|
56
|
+
timeout-minutes: 30 # a silent install that waits for input would otherwise hang for 6 hours
|
|
57
|
+
steps:
|
|
58
|
+
- uses: actions/checkout@v7 # only for .github/scripts/run-installer.ps1
|
|
59
|
+
- uses: actions/download-artifact@v8
|
|
60
|
+
with:
|
|
61
|
+
name: il2ks-windows-installer
|
|
62
|
+
path: installer
|
|
63
|
+
|
|
64
|
+
- name: Install silently
|
|
65
|
+
shell: pwsh
|
|
66
|
+
run: |
|
|
67
|
+
$exe = (Get-ChildItem installer\il2ks-setup-*.exe).FullName
|
|
68
|
+
$app = Join-Path $env:RUNNER_TEMP 'il2ks-app'
|
|
69
|
+
$logs = Join-Path $env:RUNNER_TEMP 'dserver-logs'
|
|
70
|
+
$pw = Join-Path $env:RUNNER_TEMP 'il2ks-admin-password.txt'
|
|
71
|
+
Set-Content -Path $pw -Value 'Correct-Horse-Battery-9' -Encoding ascii
|
|
72
|
+
New-Item -ItemType Directory -Force $logs | Out-Null
|
|
73
|
+
"APP=$app" | Out-File -Append -Encoding utf8 $env:GITHUB_ENV
|
|
74
|
+
$args = @('/VERYSILENT', '/SUPPRESSMSGBOXES', '/NORESTART', '/SP-', "/DIR=$app", "/LOG=$env:RUNNER_TEMP\setup.log",
|
|
75
|
+
'/NOSERVICE', '/NOFIREWALL', '/MERGETASKS=!firewall', "/LOGDIR=$logs", '/TIMEZONE=UTC',
|
|
76
|
+
'/ADMINUSER=ci', "/ADMINPASSWORDFILE=$pw")
|
|
77
|
+
.github\scripts\run-installer.ps1 -Exe $exe -LogFile "$env:RUNNER_TEMP\setup.log" -Arguments $args
|
|
78
|
+
if (Test-Path "$pw") { throw "the installer did not delete the password file" }
|
|
79
|
+
|
|
80
|
+
- name: il2ks --version and doctor from the installed copy
|
|
81
|
+
shell: pwsh
|
|
82
|
+
run: |
|
|
83
|
+
& "$env:APP\il2ks.cmd" --version
|
|
84
|
+
if ($LASTEXITCODE -ne 0) { throw "il2ks --version failed" }
|
|
85
|
+
$report = & "$env:APP\il2ks.cmd" doctor 2>&1 | Out-String
|
|
86
|
+
$code = $LASTEXITCODE
|
|
87
|
+
Write-Output $report
|
|
88
|
+
# 0 = all OK, 1 = warnings (no missions yet, no domain), 2 = errors: only that fails the job. The GitHub
|
|
89
|
+
# runner has something listening on port 80 already (shown below), which is the runner's, not ours.
|
|
90
|
+
Get-NetTCPConnection -LocalPort 80 -State Listen -ErrorAction SilentlyContinue |
|
|
91
|
+
ForEach-Object { Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue } | Format-Table Id, ProcessName
|
|
92
|
+
$errors = ([regex]::Matches($report, '\[ERROR\] ([^\r\n]*)') | ForEach-Object { $_.Groups[1].Value })
|
|
93
|
+
$unexpected = @($errors | Where-Object { $_ -notmatch '^Port 80 ' })
|
|
94
|
+
if ($code -ge 2 -and $unexpected.Count -gt 0) { throw "il2ks doctor reported errors: $($unexpected -join '; ')" }
|
|
95
|
+
if (-not (Test-Path "$env:APP\service\il2ks-service.exe")) { throw "the service wrapper is missing" }
|
|
96
|
+
if (-not (Test-Path "$env:APP\bin\caddy.exe")) { throw "caddy.exe is missing" }
|
|
97
|
+
& "$env:APP\bin\caddy.exe" version
|
|
98
|
+
if (-not (Test-Path "$env:ProgramData\il2ks\il2ks.toml")) { throw "setup did not write il2ks.toml" }
|
|
99
|
+
if (Get-Service il2ks -ErrorAction SilentlyContinue) { throw "a service was installed despite /NOSERVICE" }
|
|
100
|
+
|
|
101
|
+
- name: The site answers (il2ks web --dev from the installed Python)
|
|
102
|
+
shell: pwsh
|
|
103
|
+
run: |
|
|
104
|
+
$proc = Start-Process -FilePath "$env:APP\python\python.exe" -PassThru -NoNewWindow `
|
|
105
|
+
-ArgumentList '-m', 'il2ks', '--config', "$env:ProgramData\il2ks\il2ks.toml", 'web', '--dev', '--port', '18000'
|
|
106
|
+
$ok = $false
|
|
107
|
+
foreach ($i in 1..60) {
|
|
108
|
+
try { $r = Invoke-WebRequest -UseBasicParsing http://127.0.0.1:18000/ ; $ok = $true; break } catch { Start-Sleep 1 }
|
|
109
|
+
}
|
|
110
|
+
Stop-Process -Id $proc.Id -Force
|
|
111
|
+
if (-not $ok) { throw "the site did not answer" }
|
|
112
|
+
|
|
113
|
+
- name: Upgrade over an install with an outdated override warns in the log (silent mode)
|
|
114
|
+
shell: pwsh
|
|
115
|
+
run: |
|
|
116
|
+
# A copy of a built-in page, then its version line set back to v0: as if the new il2ks had changed that page.
|
|
117
|
+
$cfg = "$env:ProgramData\il2ks\il2ks.toml"
|
|
118
|
+
& "$env:APP\python\python.exe" -P -m il2ks --config $cfg custom copy il2ks/home.html
|
|
119
|
+
if ($LASTEXITCODE -ne 0) { throw "custom copy failed" }
|
|
120
|
+
$file = "$env:ProgramData\il2ks\custom\templates\il2ks\home.html"
|
|
121
|
+
$text = [IO.File]::ReadAllText($file)
|
|
122
|
+
$old = [regex]::Match($text, 'il2ks/home\.html v\d+').Value
|
|
123
|
+
if (-not $old) { throw "the copy has no version line" }
|
|
124
|
+
[IO.File]::WriteAllText($file, $text.Replace($old, 'il2ks/home.html v0'))
|
|
125
|
+
& "$env:APP\python\python.exe" -P -m il2ks --config $cfg custom list --problems --fail-on-problems
|
|
126
|
+
if ($LASTEXITCODE -ne 4) { throw "expected exit code 4 (override out of date), got $LASTEXITCODE" }
|
|
127
|
+
# Install the same build again over it: an upgrade (il2ks.toml exists), silent, so no message box
|
|
128
|
+
$exe = (Get-ChildItem installer\il2ks-setup-*.exe).FullName
|
|
129
|
+
$args = @('/VERYSILENT', '/SUPPRESSMSGBOXES', '/NORESTART', '/SP-', "/DIR=$env:APP", "/LOG=$env:RUNNER_TEMP\upgrade.log",
|
|
130
|
+
'/NOSERVICE', '/NOFIREWALL', '/MERGETASKS=!firewall')
|
|
131
|
+
.github\scripts\run-installer.ps1 -Exe $exe -LogFile "$env:RUNNER_TEMP\upgrade.log" -Arguments $args
|
|
132
|
+
$report = "$env:ProgramData\il2ks\logs\installer-custom-check.log"
|
|
133
|
+
if (-not (Test-Path $report)) { throw "no ${report}: the upgrade did not check the customized templates" }
|
|
134
|
+
Get-Content $report
|
|
135
|
+
if ((Get-Content $report -Raw) -notmatch 'templates/il2ks/home\.html') { throw "the report does not name the outdated override" }
|
|
136
|
+
if ((Get-Content "$env:RUNNER_TEMP\upgrade.log" -Raw) -notmatch 'customized file\(s\)') { throw "the installer log has no warning" }
|
|
137
|
+
exit 0 # $LASTEXITCODE is still 4 from the expected `custom list --fail-on-problems` above
|
|
138
|
+
|
|
139
|
+
- name: Uninstall keeps the data
|
|
140
|
+
shell: pwsh
|
|
141
|
+
run: |
|
|
142
|
+
$p = Start-Process -FilePath "$env:APP\unins000.exe" -ArgumentList '/VERYSILENT', '/SUPPRESSMSGBOXES', '/NORESTART' -Wait -PassThru
|
|
143
|
+
if ($p.ExitCode -ne 0) { throw "uninstaller exit code $($p.ExitCode)" }
|
|
144
|
+
Start-Sleep 3
|
|
145
|
+
if (Test-Path "$env:APP\python") { throw "program files are still there" }
|
|
146
|
+
if (-not (Test-Path "$env:ProgramData\il2ks\il2ks.toml")) { throw "the data folder was deleted" }
|
|
147
|
+
|
|
148
|
+
service-test:
|
|
149
|
+
# The real thing on a disposable runner: register the Windows service, start it, stop it the way Windows does, remove it.
|
|
150
|
+
# Informational until it has passed on a real runner a few times (continue-on-error), because it cannot be run elsewhere.
|
|
151
|
+
needs: build
|
|
152
|
+
if: github.event_name == 'push' || inputs.service_test
|
|
153
|
+
runs-on: windows-latest
|
|
154
|
+
timeout-minutes: 30
|
|
155
|
+
continue-on-error: true
|
|
156
|
+
steps:
|
|
157
|
+
- uses: actions/checkout@v7 # only for .github/scripts/run-installer.ps1
|
|
158
|
+
- uses: actions/download-artifact@v8
|
|
159
|
+
with:
|
|
160
|
+
name: il2ks-windows-installer
|
|
161
|
+
path: installer
|
|
162
|
+
|
|
163
|
+
- name: "Install with the service (own-proxy mode: no ports 80/443 needed)"
|
|
164
|
+
shell: pwsh
|
|
165
|
+
run: |
|
|
166
|
+
$exe = (Get-ChildItem installer\il2ks-setup-*.exe).FullName
|
|
167
|
+
$logs = Join-Path $env:RUNNER_TEMP 'dserver-logs'
|
|
168
|
+
$pw = Join-Path $env:RUNNER_TEMP 'il2ks-admin-password.txt'
|
|
169
|
+
Set-Content -Path $pw -Value 'Correct-Horse-Battery-9' -Encoding ascii
|
|
170
|
+
New-Item -ItemType Directory -Force $logs | Out-Null
|
|
171
|
+
$args = @('/VERYSILENT', '/SUPPRESSMSGBOXES', '/NORESTART', '/SP-', "/LOG=$env:RUNNER_TEMP\setup.log", '/NOFIREWALL',
|
|
172
|
+
'/HTTPS=external', '/DOMAIN=stats.example.org', "/LOGDIR=$logs", '/TIMEZONE=UTC',
|
|
173
|
+
'/ADMINUSER=ci', "/ADMINPASSWORDFILE=$pw")
|
|
174
|
+
.github\scripts\run-installer.ps1 -Exe $exe -LogFile "$env:RUNNER_TEMP\setup.log" -Arguments $args
|
|
175
|
+
|
|
176
|
+
- name: The service is running and the site answers
|
|
177
|
+
shell: pwsh
|
|
178
|
+
run: |
|
|
179
|
+
$svc = Get-Service il2ks
|
|
180
|
+
if ($svc.Status -ne 'Running') { throw "service status: $($svc.Status)" }
|
|
181
|
+
$account = (Get-CimInstance Win32_Service -Filter "Name='il2ks'").StartName
|
|
182
|
+
if ($account -ne 'NT SERVICE\il2ks') { throw "the service runs as '$account', not as its virtual account" }
|
|
183
|
+
$ok = $false
|
|
184
|
+
foreach ($i in 1..90) {
|
|
185
|
+
try {
|
|
186
|
+
# production mode redirects plain http to https unless the proxy says it already did
|
|
187
|
+
$r = Invoke-WebRequest -UseBasicParsing -Headers @{ 'X-Forwarded-Proto' = 'https'; Host = 'stats.example.org' } http://127.0.0.1:8000/
|
|
188
|
+
$ok = $true; break
|
|
189
|
+
} catch { Start-Sleep 1 }
|
|
190
|
+
}
|
|
191
|
+
if (-not $ok) { Get-ChildItem "$env:ProgramData\il2ks\logs" -Recurse | ForEach-Object { "== $($_.FullName)"; Get-Content $_.FullName -Tail 20 }; throw "the site did not answer" }
|
|
192
|
+
|
|
193
|
+
- name: Stopping the service stops il2ks gracefully and leaves nothing behind
|
|
194
|
+
shell: pwsh
|
|
195
|
+
run: |
|
|
196
|
+
Stop-Service il2ks
|
|
197
|
+
Start-Sleep 3
|
|
198
|
+
$left = Get-Process -Name python, caddy -ErrorAction SilentlyContinue | Where-Object { $_.Path -like "$env:ProgramFiles\il2ks\*" }
|
|
199
|
+
Get-ChildItem "$env:ProgramData\il2ks\logs" -Filter 'run-*.log' | ForEach-Object { Get-Content $_.FullName -Tail 12 }
|
|
200
|
+
if ($left) { throw "processes left behind: $($left.Id -join ', ')" }
|
|
201
|
+
$log = Get-ChildItem "$env:ProgramData\il2ks\logs" -Filter 'run-*.log' | ForEach-Object { Get-Content $_.FullName } | Out-String
|
|
202
|
+
if ($log -notmatch '"message": "stopped"') { throw "il2ks run did not log a clean stop (it was killed)" }
|
|
203
|
+
Start-Service il2ks
|
|
204
|
+
|
|
205
|
+
- name: Uninstall removes the service
|
|
206
|
+
shell: pwsh
|
|
207
|
+
run: |
|
|
208
|
+
$p = Start-Process -FilePath "$env:ProgramFiles\il2ks\unins000.exe" -ArgumentList '/VERYSILENT', '/SUPPRESSMSGBOXES', '/NORESTART' -Wait -PassThru
|
|
209
|
+
if ($p.ExitCode -ne 0) { throw "uninstaller exit code $($p.ExitCode)" }
|
|
210
|
+
Start-Sleep 5
|
|
211
|
+
if (Get-Service il2ks -ErrorAction SilentlyContinue) { throw "the service is still registered" }
|
|
212
|
+
if (-not (Test-Path "$env:ProgramData\il2ks\il2ks.toml")) { throw "the data folder was deleted" }
|
|
213
|
+
|
|
214
|
+
release:
|
|
215
|
+
needs: smoke
|
|
216
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
217
|
+
runs-on: ubuntu-latest
|
|
218
|
+
permissions:
|
|
219
|
+
contents: write # attach the installer to the GitHub release
|
|
220
|
+
steps:
|
|
221
|
+
- uses: actions/download-artifact@v8
|
|
222
|
+
with:
|
|
223
|
+
name: il2ks-windows-installer
|
|
224
|
+
path: installer
|
|
225
|
+
- name: Attach the installer to the release (created if the PyPI release workflow has not made one)
|
|
226
|
+
env:
|
|
227
|
+
GH_TOKEN: ${{ github.token }}
|
|
228
|
+
GH_REPO: ${{ github.repository }}
|
|
229
|
+
run: |
|
|
230
|
+
gh release view "$GITHUB_REF_NAME" > /dev/null 2>&1 || gh release create "$GITHUB_REF_NAME" --title "$GITHUB_REF_NAME" --generate-notes
|
|
231
|
+
sha256sum installer/*.exe | tee installer/SHA256SUMS.txt
|
|
232
|
+
gh release upload "$GITHUB_REF_NAME" installer/*.exe installer/SHA256SUMS.txt --clobber
|