惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 叶小钗
大猫的无限游戏
大猫的无限游戏
H
Help Net Security
G
Google Developers Blog
D
Docker
阮一峰的网络日志
阮一峰的网络日志
A
About on SuperTechFans
aimingoo的专栏
aimingoo的专栏
博客园 - 聂微东
Hugging Face - Blog
Hugging Face - Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
Apple Machine Learning Research
Apple Machine Learning Research
云风的 BLOG
云风的 BLOG
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
腾讯CDC
T
The Blog of Author Tim Ferriss
Microsoft Security Blog
Microsoft Security Blog
WordPress大学
WordPress大学
I
InfoQ
Engineering at Meta
Engineering at Meta
Stack Overflow Blog
Stack Overflow Blog
Google DeepMind News
Google DeepMind News

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
I Put TestFlight Behind a Preflight Gate Before It Can To...
Todd Sullivan · 2026-06-16 · via DEV Community

Todd Sullivan

I added a preflight gate to an iOS + watchOS app build this week because the build script had a small but annoying property: it mutated the repo before it proved the repo was safe to build.

The script stamps CFBundleVersion with a timestamp before generating the Xcode project and archiving for TestFlight. That is useful because every upload gets a monotonically increasing build number.

It is also exactly the wrong thing to do before quality checks.

If formatting or tests fail after that stamp, the working tree is now dirty for a reason unrelated to the change I was trying to ship. Small thing, but this is how build scripts become suspicious. You run them, they fail, then you have to separate your actual diff from the build system's leftovers.

So I moved the build into a fail-fast shape:

echo "==> Running preflight checks..."
"$PROJECT_DIR/scripts/preflight.sh"

BUILD_NUMBER=$(date +%Y%m%d%H%M)
sed -i '' "s/CFBundleVersion: \"[^\"]*\"/CFBundleVersion: \"$BUILD_NUMBER\"/" "$PROJECT_DIR/project.yml"

The important bit is ordering. preflight.sh runs before the build number is touched.

The gate currently has four checks:

# 1. no local surprises
git -C "$PROJECT_DIR" status --porcelain

# 2. formatting is enforced, not auto-mutated
swiftformat --lint \
  "$PROJECT_DIR/SessionzApp/" \
  "$PROJECT_DIR/SessionzKit/Sources/" \
  "$PROJECT_DIR/SessionzKit/Tests/" \
  "$PROJECT_DIR/SessionzWatch/" \
  --config "$PROJECT_DIR/.swiftformat"

# 3. local Swift package tests
swift test --package-path "$PROJECT_DIR/SessionzKit" --parallel

# 4. backend edge-function unit tests
deno test "$PROJECT_DIR/supabase/functions/_lib/"

That last line is the one I care about most.

The app has a Claude-backed plan generation flow. The mobile app sends goals, equipment, available weights, and a small training context to a backend function. The backend validates auth/subscription state, calls Claude, then returns structured JSON that becomes local SwiftData models.

I do not want the only tests for that boundary to live in an app simulator.

So I pulled the pure logic out of the Edge Function handlers into _lib/ modules and tested that directly with Deno:

// subscription.ts
export function isActiveStatus(status: string | null): boolean {
  return status === "active" || status === "trialing";
}

export function validateProductId(productId: unknown): string | null {
  return typeof productId === "string" && productId.trim().length > 0
    ? productId
    : null;
}

Same idea on the Swift side. The AI coach needs compact summaries of recent training, not an unbounded dump of every logged set. PerformanceSummary condenses the last 42 days into short lines like:

Dumbbell Floor Press: best 20 kg × 8, trained 3×
Push-up: best 20 reps (bodyweight), trained 2×

That now has regression coverage for the edge cases that tend to rot quietly: bodyweight vs weighted sets, zero-weight entries, sorting by training frequency, limiting output size, and ignoring sets outside the six-week window.

The result is not fancy CI. It is just a local quality gate that refuses to make a TestFlight archive unless the repo is clean, formatted, and both sides of the AI boundary pass tests.

This is the kind of infrastructure I like for AI features: boring checks around the non-boring part.

The model can be probabilistic. The system around it should not be.


Source: Recent Sessionz commits: scripts/preflight.sh, TestFlight build integration, Swift regression tests for plan/performance logic, and Deno tests for backend Edge Function helpers.

Tags: ai, swift, testing, devops

Status: published