DevOps - Utiliship

Utiliship has two deployable artefacts: the iOS app (distributed via App Store) and the NestJS API (containerised, runs on a cloud host).

iOS App — App Store Deployment

Bundle ID: com.paotharit.utiliship Minimum OS: iOS 16.6 Target: iPhone + iPad (universal) Distribution: Apple App Store (App Store listing) Widgets: UtilishipWidgets extension bundled in the same Xcode project

Build & Release Flow

Build commands

# Debug build (simulator)
xcodebuild -project Utiliship.xcodeproj \
           -scheme Utiliship \
           -configuration Debug build
 
# Release build (device)
xcodebuild -project Utiliship.xcodeproj \
           -scheme Utiliship \
           -configuration Release build

Monetisation

MechanismImplementation
In-app purchases (Pro)StoreKit 2 via StoreKitPurchaseService (actor)
Banner ads (free tier)AdMob GADBannerView via AdMobAdsService; withBannerAd(placement:) modifier
StoreKit configUtiliship.storekit (local config for testing)

Pro users have settingsViewModel.state.isProUser == true; ads are suppressed and nav title shows "Utiliship Pro".

Entitlements

EntitlementUsed by
com.apple.security.application-groupsWidget data sharing
aps-environment (push)UtilishipWidgetsExtension.entitlements

NestJS API — Docker Deployment

Repo: utiliship-api Runtime: Node.js 20 (slim) Port: 8080 (from process.env.PORT ?? 8080 in main.ts) Framework: NestJS with global ValidationPipe

Dockerfile

FROM node:20-slim
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
ENV NODE_ENV=production
CMD ["node", "dist/main.js"]

Build: npm ci for reproducible installs, npm run build compiles TypeScript to dist/.

Deployment Flow

Environment Variables

VariableSourceUsed by
PORTHost envmain.ts listen port
GCP_PROJECT_IDHost env / configGoogleTranslateClient
GCP_LOCATIONHost env / configGoogleTranslateClient
TRANSLATE_DEFAULT_TARGET_LANGHost env / configFallback language if targetLang omitted
GCP ADC credentialsService account / workload identityBoth Google Cloud clients

Google Cloud permissions required

APIPermission
Cloud Vision APIroles/aiplatform.user or roles/ml.developer
Cloud Translation APIroles/cloudtranslate.user