Skip to content

feat: Railway migration, Shorebird OTA, CI/CD overhaul & infrastructure docs#111

Open
teetangh wants to merge 5 commits into
devfrom
feature/infra-railway-shorebird-cicd
Open

feat: Railway migration, Shorebird OTA, CI/CD overhaul & infrastructure docs#111
teetangh wants to merge 5 commits into
devfrom
feature/infra-railway-shorebird-cicd

Conversation

@teetangh
Copy link
Copy Markdown
Contributor

Summary

Infrastructure migration and CI/CD overhaul across 4 phases, preparing for Globe.dev shutdown (April 3, 2026).

21 files changed — 572 insertions, 116 deletions.


Phase 1 — Railway Migration (backend hosting)

  • backend/main.dart — Fixed DotEnv loading for Docker/Railway using includePlatformEnvironment: true. The backend now works both locally (.env file) and in containers (platform env vars). Zero route changes needed.
  • backend/Dockerfile — Correct multi-stage build: dart_frog builddart compile exe. Fixes the plan doc's nonexistent dart build cli command.
  • backend/.dockerignore — Excludes .env, build artifacts, and non-essential files from Docker context.
  • backend/railway.toml — Railway build/deploy config with health check at /api/health.
  • backend/routes/api/health.dart — Health check endpoint returning {"status": "ok", "timestamp": "..."}.
  • .github/workflows/backend-deploy.yml — Auto-deploys backend to Railway on push to prod branch (with backend/** path filter). Includes test gate and post-deploy health check.
  • backend/.env.example — Added 8 missing env vars discovered from code analysis: STREAM_API_KEY/SECRET, SUPABASE_URL/SERVICE_ROLE_KEY, UPSTASH_REDIS_*, RESEND_API_KEY, DART_ENV, ALLOWED_ORIGINS.
  • .env.example — Updated API_BASE_URL to reference Railway production URL.

Phase 2 — Shorebird OTA Integration

  • pubspec.yaml — Added shorebird_code_push: ^2.0.5 to dependencies (NOT dev_dependencies — fixes plan doc error, this is runtime code).
  • lib/main.dart — Added silent OTA update check at startup (downloads patch in background, applies on next launch).
  • shorebird.yaml — Placeholder config. Requires shorebird init locally to generate real app_id.

Phase 3 — GitHub Actions Enhancement

  • .github/workflows/flutter-ci.yml
    • Added workflow_dispatch trigger with patch/release choice
    • Updated branches: main/developprod/dev
    • Added tag-based triggers (v*.*.*)
    • Fixed deprecated flutter pub rundart run (2 occurrences)
    • Added test-backend job (analyze + test on every push/PR)
    • Added shorebird-release job (after store deploys, on tags)
    • Added shorebird-patch job (on hotfix/* push or manual dispatch)

Phase 4 — Documentation

  • CLAUDE.md — Created (was referenced in README but missing). Covers: Railway hosting, Shorebird OTA, update decision tree, branch strategy, env config approach, CI/CD workflows, known gotchas.
  • README.md — Updated overview table (backend → Railway, added OTA row), backend setup section (Railway production info), CI/CD section (9 jobs table + hotfix workflow).
  • backend/README.md — Full rewrite: Railway hosting, complete env vars table (21 vars), API routes with health check, Docker build instructions.
  • docs/deployment/03-migration-checklist.md — Comprehensive verification checklist for all 4 phases + post-migration validation.
  • docs/deployment/ — Renamed files to numbered kebab-case: 01-deployment-strategy.md, 02-migration-and-cicd-plan.md, 03-migration-checklist.md.
  • docs/README.md — Updated links to new deployment doc filenames.
  • .mcp.json.example — Added Railway MCP server config.

Critical fixes vs. the original migration plan doc

# Plan doc issue What we did instead
1 dart build cli (doesn't exist) dart compile exe
2 String.fromEnvironment + --dart-define for API_BASE_URL Preserved envied + .env approach
3 Targets main branch Uses prod (created from dev)
4 DotEnv()..load(['.env']) throws in Docker DotEnv(includePlatformEnvironment: true) + conditional .env load
5 References 4 workflows that don't exist Only flutter-ci.yml exists — kept it, added jobs
6 shorebird_code_push in dev_dependencies Moved to dependencies (runtime code)
7 Backend env vars list incomplete (12 vars) Complete list from code analysis (21 vars)
8 Full CI replacement drops .env generation Preserved existing .env creation pattern

Next steps (manual, post-merge)

Immediate (before April 3)

  1. Create prod branch from dev after merging this PR
  2. Create Railway project — use Railway MCP (@railway/mcp-server) or dashboard
  3. Set all 21 Railway env vars — full list in backend/.env.example
  4. Add GitHub Secrets (currently zero exist):
    • RAILWAY_TOKEN — Railway → Account Settings → Tokens
    • PRODUCTION_API_BASE_URL — Railway assigned URL
    • SHOREBIRD_TOKENshorebird login locally
    • All CI secrets: SUPABASE_URL, SUPABASE_ANON_KEY, STREAM_API_KEY, RAZORPAY_KEY_ID, STRIPE_PUBLISHABLE_KEY, API_BASE_URL, CODECOV_TOKEN, Android signing keys, iOS signing keys, App Store Connect keys
  5. Run shorebird init locally to generate real app_id in shorebird.yaml
  6. Update webhook URLs in Stripe/Razorpay dashboards to Railway URL
  7. Test deployment: push to prod → verify Railway auto-deploy + health check

Validation checklist

See docs/deployment/03-migration-checklist.md for the full verification checklist.

Test plan

  • Backend dart analyze passes with zero errors (confirmed: only 2 pre-existing infos)
  • flutter pub get resolves successfully (confirmed: shorebird_code_push installed)
  • Docker build: cd backend && docker build -t familiarise-api .
  • Docker run: docker run -p 8080:8080 --env-file .env familiarise-api
  • Health check: curl http://localhost:8080/api/health returns {"status":"ok"}
  • Push to prod triggers backend-deploy.yml
  • Push to hotfix/* triggers shorebird-patch job
  • Full CI passes on this PR

🤖 Generated with Claude Code

teetangh and others added 2 commits March 28, 2026 21:10
…re docs

- Fix backend DotEnv loading for Docker/Railway with includePlatformEnvironment
- Add Dockerfile, railway.toml, .dockerignore, and health check endpoint
- Add backend-deploy.yml workflow for auto-deploy to Railway on push to prod
- Add complete Railway env vars list (21 vars) to backend/.env.example
- Integrate shorebird_code_push for silent OTA patches
- Add shorebird-release and shorebird-patch jobs to flutter-ci.yml
- Add workflow_dispatch trigger, fix deprecated flutter pub run commands
- Update branches from main/develop to prod/dev
- Create CLAUDE.md with infrastructure, OTA, and branch strategy docs
- Rename deployment docs to numbered kebab-case convention

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@teetangh teetangh self-assigned this Mar 28, 2026
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces infrastructure for hosting the Dart Frog backend on Railway and implementing Over-The-Air (OTA) updates using Shorebird. Key changes include a multi-stage Dockerfile, Railway configuration, a health check endpoint, and comprehensive documentation for the new system architecture. Feedback focuses on improving the backend container's reliability by switching to a distroless base image to support SSL and glibc, ensuring app resilience by wrapping Shorebird update checks in error handling, and correcting documentation regarding environment variable precedence.

Comment thread backend/Dockerfile Outdated
RUN dart compile exe build/bin/server.dart -o build/bin/server

# ── Stage 2: Runtime ────────────────────────────────────────
FROM scratch
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The scratch base image is extremely minimal and lacks essential components like root SSL certificates and standard C libraries (glibc). This will cause two critical issues:

  1. HTTPS failures: Outgoing requests to services like Sentry, GitHub, or Resend will fail with TLS/SSL handshake errors.
  2. Runtime errors: The AOT-compiled Dart executable is dynamically linked to glibc, which is absent in scratch, causing the container to fail at startup.

Using a distroless image is a best practice that solves both problems by providing a minimal, secure environment with these necessary components.

FROM gcr.io/distroless/cc-debian12

Comment thread lib/main.dart
Comment on lines +41 to +46
final shorebirdCodePush = ShorebirdCodePush();
final isUpdateAvailable =
await shorebirdCodePush.isNewPatchAvailableForDownload();
if (isUpdateAvailable) {
await shorebirdCodePush.downloadUpdateIfAvailable();
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The Shorebird update check involves network requests and could throw an exception (e.g., due to network issues or server errors). An unhandled exception here would prevent runApp from being called, causing the app to fail on startup. To make the app more resilient, this logic should be wrapped in a try-catch block to handle potential failures gracefully.

Suggested change
final shorebirdCodePush = ShorebirdCodePush();
final isUpdateAvailable =
await shorebirdCodePush.isNewPatchAvailableForDownload();
if (isUpdateAvailable) {
await shorebirdCodePush.downloadUpdateIfAvailable();
}
try {
final shorebirdCodePush = ShorebirdCodePush();
final isUpdateAvailable =
await shorebirdCodePush.isNewPatchAvailableForDownload();
if (isUpdateAvailable) {
await shorebirdCodePush.downloadUpdateIfAvailable();
}
} catch (e, s) {
// Silently log the error and continue app startup.
Sentry.captureException(e, stackTrace: s);
}

Comment thread backend/main.dart
// Load environment variables.
// includePlatformEnvironment: true merges Platform.environment into the map,
// so env vars injected by Docker/Railway are accessible via env['KEY'].
// The .env file (if present) overrides platform env vars.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This comment incorrectly states that the .env file overrides platform environment variables. The dotenv package's load() method does not overwrite existing variables. Since includePlatformEnvironment: true loads platform variables first, they will take precedence. The comment should be corrected to reflect this behavior, which is standard and desirable for containerized environments where platform variables are the source of truth.

Suggested change
// The .env file (if present) overrides platform env vars.
// The .env file provides local defaults, but platform variables (from Docker/Railway) will override them.

teetangh and others added 3 commits March 29, 2026 00:52
…nk, runtime

- Switch base image from dart:stable to ghcr.io/cirruslabs/flutter:stable
  (prisma_flutter_connector requires Flutter SDK for dependency resolution)
- Add Prisma client generation step (lib/generated/ is gitignored)
- Add build_runner step for freezed/json codegen on generated models
- Replace prisma/schema.prisma symlink with real file copy
  (Docker cannot follow symlinks outside build context)
- Switch runtime from scratch to debian:bookworm-slim
  (Flutter image lacks /runtime/ that dart:stable provides)
- Add detailed build notes in Dockerfile documenting all failure modes
- Rename service references from familiarise-api to familiarise-mobile-api
- Update migration checklist with completed items

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Shorebird initialized with app_id: f9b217a0-1007-48a5-bd41-d381568e23f1
- shorebird.yaml added to Flutter assets in pubspec.yaml (by shorebird init)
- Track ios/Podfile.lock in git (was gitignored — locks CocoaPods versions
  for reproducible builds, same rationale as pubspec.lock)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Marked Railway project as created and connected to familiarise-mobile-api.
- Confirmed all environment variables are set in Railway dashboard.
- Verified database URLs and backend deployment status.
- Updated health check and auth endpoint testing details.
- Completed Shorebird initialization and committed shorebird.yaml with real app_id.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@teetangh teetangh requested a review from Copilot March 28, 2026 20:16
@teetangh
Copy link
Copy Markdown
Contributor Author

/gemini review

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates backend hosting from Globe.dev to Railway, adds Shorebird OTA support for Flutter, and updates CI/CD + documentation to align with the new infrastructure and branch strategy ahead of Globe.dev shutdown.

Changes:

  • Add Railway deployment support (Dockerfile build, Railway config, /api/health endpoint, backend env loading adjustments).
  • Integrate Shorebird OTA (dependency + startup patch check) and extend GitHub Actions workflows for backend tests/deploy and Shorebird release/patch.
  • Add/refresh deployment documentation and checklists.

Reviewed changes

Copilot reviewed 20 out of 25 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
shorebird.yaml Adds Shorebird app configuration (app_id, auto-update notes).
pubspec.yaml Adds Shorebird dependency and includes shorebird.yaml in assets.
pubspec.lock Locks Shorebird dependency version.
lib/main.dart Adds Shorebird patch availability check during startup.
ios/Podfile.lock Introduces tracked CocoaPods lockfile for reproducible iOS builds.
docs/deployment/03-migration-checklist.md Adds a migration verification checklist across phases.
docs/deployment/02-migration-and-cicd-plan.md Updates plan references (service name/URLs) for Railway migration.
docs/deployment/01-deployment-strategy.md Adds a deployment strategy guide (backend + mobile CI/CD options).
docs/README.md Updates documentation index to new deployment docs.
backend/routes/api/health.dart Implements Railway health check endpoint.
backend/railway.toml Adds Railway build/deploy + healthcheck configuration.
backend/prisma/schema.prisma Replaces prior schema symlink with a full schema copy for Docker/Railway builds.
backend/main.dart Updates dotenv loading to support platform env vars (Docker/Railway) with optional .env.
backend/README.md Rewrites backend docs (local dev, env vars, routes, Railway/Docker deployment).
backend/Dockerfile Adds multi-stage Docker build for Dart Frog + Prisma + build_runner + AOT compilation.
backend/.env.example Expands backend env var examples (Stream/Supabase/Upstash/Resend/etc).
backend/.dockerignore Reduces Docker build context (excluding env, build outputs, etc.).
README.md Updates repo overview, backend setup, and CI/CD documentation for Railway + Shorebird.
CLAUDE.md Adds infrastructure/CI conventions and gotchas for contributors/agents.
.mcp.json.example Adds Railway MCP server configuration.
.gitignore Stops ignoring ios/Podfile.lock to track it in git.
.github/workflows/flutter-ci.yml Updates triggers, replaces deprecated commands, adds backend test + Shorebird jobs.
.github/workflows/backend-deploy.yml Adds Railway deploy workflow with tests + post-deploy health check.
.env.example Updates API base URL guidance for local vs Railway production.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread backend/README.md
Comment on lines +64 to +68
| GET | `/api/health` | Health check (used by Railway) |
| POST | `/api/auth/sign-in` | Sign in |
| POST | `/api/auth/sign-up` | Register |
| DELETE | `/api/auth/sign-out` | Sign out |
| GET | `/api/auth/session` | Get current session |
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The API routes table is inaccurate for auth and Stream endpoints. For example, the codebase uses POST /api/auth/email/sign-in and POST /api/auth/email/sign-up (not /api/auth/sign-in or /api/auth/sign-up), POST /api/auth/sign-out (not DELETE), and POST /api/stream/token (not GET). Please update the table to match the actual Dart Frog routes so the README doesn’t mislead deployers/clients.

Copilot uses AI. Check for mistakes.
Comment thread pubspec.yaml
- assets/images/
- assets/icons/
- assets/fonts/
- shorebird.yaml
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shorebird.yaml is being bundled as a Flutter asset, but there’s no runtime code in the repo that reads it (it’s typically a Shorebird CLI config file). Unless the app needs to load this file at runtime, consider removing it from flutter/assets to avoid shipping config-only metadata in the app bundle.

Suggested change
- shorebird.yaml

Copilot uses AI. Check for mistakes.
Comment thread backend/Dockerfile
Comment on lines +21 to +22
# with a real file copy. If the web schema changes, re-copy it:
# cp ~/Desktop/familiarise_web/prisma/schema.prisma backend/prisma/schema.prisma
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Dockerfile comment includes a developer-specific local path (cp ~/Desktop/...) for re-copying the Prisma schema. Since this repo will be used by multiple developers/CI, it’d be better to phrase this generically (e.g., “copy from the web repo path”) or point to an internal script that performs the sync, rather than referencing a specific machine path.

Suggested change
# with a real file copy. If the web schema changes, re-copy it:
# cp ~/Desktop/familiarise_web/prisma/schema.prisma backend/prisma/schema.prisma
# with a real file copy. If the web schema changes, re-copy the updated
# familiarise_web/prisma/schema.prisma into backend/prisma/schema.prisma.

Copilot uses AI. Check for mistakes.
Comment thread backend/README.md

# Copy environment file
# Generate Prisma client
dart run orm generate
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dart run orm generate won’t work in backend/ as-is: backend/pubspec.yaml doesn’t declare a dependency named orm and there’s no local package providing that executable. The README should use the actual Prisma generation command used by this repo (e.g., dart run prisma_flutter_connector:generate ... or whatever your canonical script is) so new developers can follow it successfully.

Suggested change
dart run orm generate
dart run prisma_flutter_connector:generate

Copilot uses AI. Check for mistakes.
name: Shorebird Release
needs: [deploy-android, deploy-ios]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shorebird-release is configured to run on tag pushes (if: startsWith(github.ref, 'refs/tags/')) but it needs: [deploy-android, deploy-ios]. Those deploy jobs only run when github.event_name == 'release', so on a tag push they will be skipped and this job won’t run either. To make Shorebird releases actually happen on tags, adjust the dependencies/conditions (e.g., depend on the build jobs for tag pushes, or run Shorebird release on release events instead of tag pushes).

Suggested change
if: startsWith(github.ref, 'refs/tags/')
if: github.event_name == 'release' && startsWith(github.ref, 'refs/tags/')

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +20
inputs:
deploy_type:
description: 'Deployment type'
required: false
default: 'patch'
type: choice
options:
- patch
- release
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

workflow_dispatch defines an input deploy_type, but it isn’t referenced anywhere in job if: conditions or steps. As written, manually dispatching the workflow will always run shorebird-patch (and never shorebird-release unless also pushing a tag), regardless of the selected option. Either wire inputs.deploy_type into the job conditions, or remove the unused input to avoid confusion.

Suggested change
inputs:
deploy_type:
description: 'Deployment type'
required: false
default: 'patch'
type: choice
options:
- patch
- release

Copilot uses AI. Check for mistakes.
Comment on lines +60 to +62
curl --fail --retry 5 --retry-delay 10 \
"${{ secrets.PRODUCTION_API_BASE_URL }}/api/health" || \
echo "::warning::Health check failed - check Railway dashboard"
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The post-deploy health check can’t fail the workflow because it’s followed by || echo "::warning::...". That means a bad deploy still reports success, which undermines the purpose of a health check gate. If you want this to block approval/deploy, let curl --fail ... exit non-zero (or explicitly exit 1 on failure) so the job fails when the service is unhealthy.

Suggested change
curl --fail --retry 5 --retry-delay 10 \
"${{ secrets.PRODUCTION_API_BASE_URL }}/api/health" || \
echo "::warning::Health check failed - check Railway dashboard"
if ! curl --fail --retry 5 --retry-delay 10 "${{ secrets.PRODUCTION_API_BASE_URL }}/api/health"; then
echo "::warning::Health check failed - check Railway dashboard"
exit 1
fi

Copilot uses AI. Check for mistakes.
Comment thread lib/main.dart
Comment on lines +39 to +46
// Check for Shorebird OTA patches (downloads in background,
// applies silently on next app launch)
final shorebirdCodePush = ShorebirdCodePush();
final isUpdateAvailable =
await shorebirdCodePush.isNewPatchAvailableForDownload();
if (isUpdateAvailable) {
await shorebirdCodePush.downloadUpdateIfAvailable();
}
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Shorebird update check is awaited during app startup (before runApp). Even though the comment says “downloads in background”, isNewPatchAvailableForDownload() and downloadUpdateIfAvailable() will block initialization and can noticeably slow cold start when network is slow. Consider moving this after runApp (or running it unawaited / with a short timeout) so app launch isn’t gated on the OTA check.

Copilot uses AI. Check for mistakes.
Comment thread README.md

# Start the development server
dart_frog dev
dart run orm generate # Generate Prisma client
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The backend setup instructions reference dart run orm generate, but backend/pubspec.yaml doesn’t include an orm package/executable. This command will fail for anyone following the README. Please update this to the repo’s actual Prisma generation command (or a script you expect contributors to run) to keep the setup steps accurate.

Suggested change
dart run orm generate # Generate Prisma client
npx prisma generate # Generate Prisma client

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request migrates the backend to Railway and integrates Shorebird for over-the-air (OTA) updates. Key changes include the addition of a production Dockerfile for the Dart Frog API, the implementation of a health check endpoint, and extensive updates to the project documentation and CI/CD workflows. A redundancy was identified in the Shorebird configuration where the auto_update property should be explicitly set to false to prevent conflict with the manual update logic implemented in the Flutter application.

Comment thread shorebird.yaml
# If auto_update: false, you will need to use package:shorebird_code_push to trigger updates.
# https://pub.dev/packages/shorebird_code_push
# Uncomment the following line to disable automatic updates.
# auto_update: false
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The auto_update property is currently commented out, meaning it defaults to true. When enabled, Shorebird automatically checks for and downloads patches at launch, which makes the manual update logic you've added in lib/main.dart redundant.

Since your code in main.dart already handles checking for updates, you should uncomment this line to explicitly set auto_update: false. This will prevent redundant checks and ensure the update behavior is solely controlled by your code, as intended.

auto_update: false

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 25 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

docs/deployment/02-migration-and-cicd-plan.md:1035

  • In this CLAUDE.md snippet, auto-deploy is described as triggering on pushes to main, but the branch strategy in this PR is prod for production deploys. Update the snippet to reference prod so the generated docs match the actual workflow triggers.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +314 to +346
shorebird-release:
name: Shorebird Release
needs: [deploy-android, deploy-ios]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')

steps:
- uses: actions/checkout@v4

- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
channel: stable
cache: true

- name: Install dependencies
run: flutter pub get

- name: Generate code
run: dart run build_runner build --delete-conflicting-outputs

- name: Install Shorebird CLI
uses: shorebirdtech/setup-shorebird@v1

- name: Create Shorebird release (Android)
run: shorebird release android --flutter-version ${{ env.FLUTTER_VERSION }}
env:
SHOREBIRD_TOKEN: ${{ secrets.SHOREBIRD_TOKEN }}

- name: Create Shorebird release (iOS)
run: shorebird release ios --flutter-version ${{ env.FLUTTER_VERSION }}
env:
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shorebird release ios requires a macOS runner (Xcode toolchain). Running the Shorebird release job on ubuntu-latest will fail for iOS; split Android/iOS into separate jobs (ubuntu for android, macos for ios) or use a matrix with per-platform runs-on.

Copilot uses AI. Check for mistakes.
Comment on lines +353 to +386
shorebird-patch:
name: Shorebird Hotfix Patch
runs-on: ubuntu-latest
if: |
github.event_name == 'workflow_dispatch' ||
startsWith(github.ref, 'refs/heads/hotfix/')

steps:
- uses: actions/checkout@v4

- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
channel: stable
cache: true

- name: Install dependencies
run: flutter pub get

- name: Generate code
run: dart run build_runner build --delete-conflicting-outputs

- name: Install Shorebird CLI
uses: shorebirdtech/setup-shorebird@v1

- name: Apply patch (Android)
run: shorebird patch android
env:
SHOREBIRD_TOKEN: ${{ secrets.SHOREBIRD_TOKEN }}

- name: Apply patch (iOS)
run: shorebird patch ios
env:
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This job runs on ubuntu-latest but executes shorebird patch ios, which typically requires macOS/Xcode. To avoid guaranteed failures, run the iOS patch step on a macOS runner (separate job or matrix) and keep Android patching on Linux.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants