feat(mobile): React Native + Expo app — MVP (auth, dashboard, weight) + shared core #314
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 | |
| on: | |
| push: | |
| branches: ['**'] | |
| tags: ['v*'] | |
| pull_request: | |
| branches: [main] | |
| jobs: | |
| test: | |
| name: Go unit tests | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version: '1.26' | |
| cache-dependency-path: backend/go.sum | |
| - run: cd backend && go mod download | |
| - run: cd backend && go test ./controllers/ -timeout 30s | |
| unit: | |
| name: Web unit tests | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| cache-dependency-path: web/package-lock.json | |
| - run: cd web && npm ci | |
| - run: cd web && npm run coverage # runs the unit suite + prints a coverage report (not gated) | |
| - uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: web-coverage | |
| path: web/coverage/ | |
| retention-days: 7 | |
| e2e: | |
| name: Playwright E2E | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Create .env | |
| run: | | |
| echo "JWT_SECRET=ci-test-secret-$(openssl rand -hex 16)" >> .env | |
| echo "PORT=80" >> .env | |
| - uses: docker/setup-buildx-action@v3 | |
| - name: Build images with layer cache | |
| run: | | |
| docker buildx bake \ | |
| --set "backend.cache-from=type=gha,scope=lyftr-backend" \ | |
| --set "backend.cache-to=type=gha,scope=lyftr-backend,mode=max" \ | |
| --set "frontend.cache-from=type=gha,scope=lyftr-frontend" \ | |
| --set "frontend.cache-to=type=gha,scope=lyftr-frontend,mode=max" \ | |
| --load | |
| - name: Start stack | |
| run: docker compose up -d --wait | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| cache-dependency-path: web/package-lock.json | |
| - run: cd web && npm ci | |
| - name: Cache Playwright browsers | |
| uses: actions/cache@v4 | |
| id: playwright-cache | |
| with: | |
| path: ~/.cache/ms-playwright | |
| key: playwright-${{ runner.os }}-${{ hashFiles('web/package-lock.json') }} | |
| - name: Install Playwright browsers | |
| if: steps.playwright-cache.outputs.cache-hit != 'true' | |
| run: cd web && npx playwright install chromium webkit | |
| - name: Install Playwright system dependencies | |
| run: cd web && npx playwright install-deps chromium webkit | |
| - name: Wait for demo user to be seeded | |
| run: | | |
| timeout 90 bash -c 'until curl -sf -X POST http://localhost/api/v1/auth/login \ | |
| -H "Content-Type: application/json" \ | |
| -d "{\"email\":\"demo@lyftr.local\",\"password\":\"password123\"}" \ | |
| | grep -q "token"; do sleep 3; done' | |
| - name: Run E2E tests | |
| run: cd web && npm run test:e2e:docker | |
| - uses: actions/upload-artifact@v4 | |
| if: failure() | |
| with: | |
| name: playwright-report | |
| path: web/playwright-report/ | |
| retention-days: 7 | |
| version-smoke: | |
| name: Version injection smoke test | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Build backend image with a known version | |
| run: docker build --build-arg VERSION=smoke-9.9.9 -t lyftr-backend:smoke ./backend | |
| - name: Assert the binary reports the injected version | |
| run: | | |
| set -euo pipefail | |
| out=$(docker run --rm lyftr-backend:smoke --version) | |
| echo "version output: $out" | |
| echo "$out" | grep -q 'smoke-9.9.9' | |
| build-backend: | |
| name: Build & push backend image | |
| needs: [test, unit, e2e, version-smoke] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 # full history so `git describe --tags` resolves | |
| - name: Resolve version | |
| id: ver | |
| run: echo "version=$(git describe --tags --always)" >> "$GITHUB_OUTPUT" | |
| - uses: docker/setup-qemu-action@v3 | |
| - uses: docker/setup-buildx-action@v3 | |
| - uses: docker/login-action@v3 | |
| if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - uses: docker/metadata-action@v5 | |
| id: meta | |
| with: | |
| images: ${{ secrets.DOCKERHUB_USERNAME }}/lyftr-backend | |
| tags: | | |
| type=ref,event=tag | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| - uses: docker/build-push-action@v6 | |
| with: | |
| context: ./backend | |
| platforms: linux/amd64,linux/arm64,linux/arm/v7 | |
| push: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') }} | |
| tags: ${{ steps.meta.outputs.tags }} | |
| build-args: | | |
| VERSION=${{ steps.ver.outputs.version }} | |
| cache-from: type=gha,scope=lyftr-backend | |
| cache-to: type=gha,scope=lyftr-backend,mode=max | |
| build-frontend: | |
| name: Build & push frontend image | |
| needs: [test, unit, e2e] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: docker/setup-qemu-action@v3 | |
| - uses: docker/setup-buildx-action@v3 | |
| - uses: docker/login-action@v3 | |
| if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - uses: docker/metadata-action@v5 | |
| id: meta | |
| with: | |
| images: ${{ secrets.DOCKERHUB_USERNAME }}/lyftr-frontend | |
| tags: | | |
| type=ref,event=tag | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| - uses: docker/build-push-action@v6 | |
| with: | |
| context: ./web | |
| platforms: linux/amd64,linux/arm64,linux/arm/v7 | |
| push: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') }} | |
| tags: ${{ steps.meta.outputs.tags }} | |
| cache-from: type=gha,scope=lyftr-frontend | |
| cache-to: type=gha,scope=lyftr-frontend,mode=max | |
| deploy-demo: | |
| name: Deploy to Fly.io | |
| needs: [test, unit, e2e, version-smoke] | |
| if: github.ref == 'refs/heads/main' && github.event_name == 'push' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 # full history so `git describe --tags` resolves | |
| - uses: superfly/flyctl-actions/setup-flyctl@master | |
| - name: Deploy | |
| run: flyctl deploy --remote-only --build-arg VERSION="$(git describe --tags --always)" | |
| env: | |
| FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }} |