Fix iOS PWA safe-area insets on detail panel, dialogs, mobile chrome #265
Workflow file for this run
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: CI/CD | |
| permissions: | |
| contents: read | |
| on: | |
| push: | |
| branches: [main] | |
| tags: ["v*"] | |
| # Skip the run entirely when only doc / Claude / screenshot paths | |
| # change — none of these end up in the published image, and the | |
| # Docker build + Playwright runs are the slow ones to spin up. A | |
| # change that mixes a doc edit with a real source edit still | |
| # triggers, because GitHub triggers when *any* changed path is | |
| # outside this list. | |
| paths-ignore: | |
| - '**/*.md' | |
| - 'docs/**' | |
| - 'LICENSE' | |
| - 'scripts/take_screenshots.js' | |
| pull_request: | |
| branches: [main] | |
| paths-ignore: | |
| - '**/*.md' | |
| - 'docs/**' | |
| - 'LICENSE' | |
| - 'scripts/take_screenshots.js' | |
| workflow_dispatch: | |
| inputs: | |
| tag: | |
| description: "Extra tag alongside :latest (e.g. v1.2.0). Leave blank for just :latest." | |
| required: false | |
| default: "" | |
| jobs: | |
| # Detect which top-level areas changed so downstream jobs can skip | |
| # expensive work (Docker build, Cloudflare deploy) when irrelevant. | |
| changes: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| app: ${{ steps.filter.outputs.app }} | |
| relay: ${{ steps.filter.outputs.relay }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: dorny/paths-filter@v4 | |
| id: filter | |
| with: | |
| filters: | | |
| app: | |
| - 'dotnet/**' | |
| - 'app/**' | |
| - 'scripts/fetch_plane_shapes.py' | |
| relay: | |
| - 'relay-worker/**' | |
| check: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: "10.0.x" | |
| - name: Restore | |
| working-directory: dotnet | |
| run: dotnet restore FlightJar.slnx | |
| - name: Format check | |
| working-directory: dotnet | |
| run: dotnet format FlightJar.slnx --verify-no-changes --no-restore | |
| - name: Build | |
| working-directory: dotnet | |
| run: dotnet build FlightJar.slnx -c Release --no-restore /p:TreatWarningsAsErrors=true | |
| - name: Test | |
| working-directory: dotnet | |
| run: dotnet test FlightJar.slnx -c Release --no-build --logger "console;verbosity=normal" | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: "22" | |
| - name: Node tests (frontend modules) | |
| # Glob expanded by bash — Node 22 stopped treating the bare | |
| # directory path as a discovery target and tries to resolve it | |
| # as a single module instead. | |
| run: node --test tests/js/*.test.js | |
| - name: Relay worker type check | |
| working-directory: relay-worker | |
| run: npm install && npm run check | |
| e2e: | |
| # Playwright smoke suite against the real .NET backend in its | |
| # no-BEAST harness mode (see playwright.config.js webServer env). | |
| # Runs in parallel with `check`; `publish` gates on this one too | |
| # so a broken UI also blocks the image push. | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: "10.0.x" | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: "22" | |
| # Cache the Playwright browser binaries across runs. npm install | |
| # doesn't need its own cache since we deliberately don't commit a | |
| # lockfile (single dep, resolves fast; no cross-CI reproducibility | |
| # concern). The cache key includes the @playwright/test version | |
| # pinned in package.json so a bump invalidates cleanly. | |
| - name: Cache Playwright browsers | |
| uses: actions/cache@v5 | |
| with: | |
| path: ~/.cache/ms-playwright | |
| key: playwright-${{ runner.os }}-${{ hashFiles('package.json') }} | |
| - name: Install Playwright + Chromium | |
| run: | | |
| npm install | |
| npx playwright install --with-deps chromium | |
| - name: Stage auto-generated assets | |
| # tar1090 silhouettes aren't committed; fetch them so the app serves | |
| # a complete page. Python interpreter is preinstalled on GitHub runners. | |
| env: | |
| TAR1090_SHAPES_DEST: ${{ github.workspace }}/app/static/tar1090_shapes.js | |
| run: python3 scripts/fetch_plane_shapes.py | |
| - name: Publish backend for Playwright | |
| run: dotnet publish dotnet/src/FlightJar.Api/FlightJar.Api.csproj -c Release -o dotnet-publish | |
| - name: Playwright tests | |
| run: npm run test:e2e | |
| - name: Upload report on failure | |
| if: failure() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: playwright-report | |
| path: playwright-report/ | |
| retention-days: 7 | |
| publish: | |
| # Build + push the Docker image only when application files changed | |
| # (dotnet/, app/, fetch_plane_shapes.py). A relay-worker-only push | |
| # skips this job and goes straight to deploy-relay instead. | |
| needs: [check, e2e, changes] | |
| if: >- | |
| github.event_name == 'workflow_dispatch' || | |
| (github.event_name == 'push' && | |
| needs.changes.outputs.app == 'true' && | |
| (github.ref == 'refs/heads/main' || | |
| startsWith(github.ref, 'refs/tags/v'))) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: docker/setup-qemu-action@v4 | |
| - uses: docker/setup-buildx-action@v4 | |
| - name: Log in to Docker Hub | |
| uses: docker/login-action@v4 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Compute image tags | |
| id: meta | |
| uses: docker/metadata-action@v6 | |
| with: | |
| images: ${{ secrets.DOCKERHUB_USERNAME }}/flightjar | |
| tags: | | |
| type=raw,value=latest | |
| type=sha,format=short,prefix=git- | |
| type=semver,pattern={{version}} | |
| type=raw,value=${{ inputs.tag }},enable=${{ inputs.tag != '' }} | |
| # Rolling weekly key for the upstream-data layer in the Dockerfile. | |
| # Per-commit pushes hit the cache (so a code-only change doesn't | |
| # re-pull aircraft_db / airports / navaids / airlines / shapes); | |
| # a real upstream change comes in within 7 days. Bump-on-demand: | |
| # change this format string or trigger a workflow_dispatch with | |
| # --no-cache equivalent. | |
| - name: Compute weekly data cachebust | |
| id: cachebust | |
| run: echo "value=$(date -u +%Y-W%V)" >> "$GITHUB_OUTPUT" | |
| - name: Build and push | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: . | |
| file: dotnet/Dockerfile | |
| platforms: linux/amd64,linux/arm64 | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| # DATA_CACHEBUST is a weekly ISO-week string (YYYY-WNN) so | |
| # commits don't re-pull unchanged upstream files but a real | |
| # upstream change comes in within ~7 days. Everything else | |
| # (dotnet publish, static-asset copy) still caches normally | |
| # between builds. FLIGHTJAR_VERSION stamps the image with | |
| # the commit that produced it; /api/stats exposes it and the | |
| # About dialog shows the short form next to the title. | |
| build-args: | | |
| DATA_CACHEBUST=${{ steps.cachebust.outputs.value }} | |
| FLIGHTJAR_VERSION=${{ github.sha }} | |
| POSTHOG_API_KEY=${{ vars.POSTHOG_API_KEY }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| deploy-relay: | |
| # Deploy the Cloudflare Worker relay when relay-worker/ files change. | |
| # Gates on `check` so a TypeScript error blocks the deploy. | |
| needs: [check, changes] | |
| if: >- | |
| github.event_name == 'workflow_dispatch' || | |
| (github.event_name == 'push' && | |
| needs.changes.outputs.relay == 'true' && | |
| github.ref == 'refs/heads/main') | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: "22" | |
| - name: Install dependencies | |
| working-directory: relay-worker | |
| run: npm install | |
| - name: Deploy to Cloudflare Workers | |
| working-directory: relay-worker | |
| env: | |
| CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} | |
| CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} | |
| run: npx wrangler deploy |