Maintainer guide to the Pipedash iOS release. Covers files, versions, workflows, secrets, App Review demo access, signing, disabled features, tests and App Store screenshots.
The iOS app is the crates/pipedash-desktop Tauri app built for iOS. Every build generates the Xcode project, and Git ignores crates/pipedash-desktop/gen. Everything iOS needs lives in the ios directory or in crates/pipedash-desktop/Info.ios.plist. The Mobile page describes the app from the user side.
Files
File paths link to the main branch on GitHub.
| Path | What it is |
|---|---|
ios/fastlane/Fastfile | Build, simulator capture, screenshot export and upload, and release lanes |
ios/xcode/PrivacyInfo.xcprivacy | Privacy manifest copied into the app target |
ios/xcode/pipedash.entitlements | App entitlements without APNs access |
ios/fastlane/metadata/en-US/release_notes.txt | The "What's New" text that release sends |
ios/fastlane/metadata/en-US/description.txt | The app description that release sends, including the foreground-refresh limits |
ios/fastlane/metadata/en-US/support_url.txt | The support URL that release sends. It points to the support page, which lists an email contact |
ios/fastlane/review_notes.txt | App Review instructions, with the demo token, repository and workflow filled in at release time |
ios/fastlane/app_review_demo.rb | Read-only GitHub access checks before release signing or submission |
ios/fastlane/ios_project.rb | App version, disabled-feature checks and export profile setup |
crates/pipedash-desktop/icons/ios/app-icon-1024.png | Full-bleed App Store icon without alpha |
ios/app-store-screenshots | Screenshot editor, saved decks, mock captures and export scripts |
ios/fastlane/screenshots/en-US/ | Generated iPhone and iPad images for upload. Git ignores this directory |
Versions
- App version: the release version with the major number raised by 1, because the App Store already shipped
1.0. Releasev0.4.0ships as1.4.0.mise run bump:*keeps working, and the Fastfile derives the iOS version. - Build number: the latest build in App Store Connect plus 1.
- Minimum iOS:
15.0. The valuebundle.iOS.minimumSystemVersionintauri.ios.conf.jsonsets it. Tauri maps it toIPHONEOS_DEPLOYMENT_TARGET. The schema of the installed Tauri CLI also defaults to15.0.
Workflows
Both workflows run on the macos-26 runner.
ios-check.yml: runs on pull requests that touch the app and supports manual runs on a feature branch. The first job runs the Ruby helper tests and publishing guards. It builds an unsigned IPA and checks the disabled background capabilities, theInfo.plistkeys, export compliance, the app icon and the required-reason APIs. The second job builds for the simulator, starts the app on iPhone and iPad and uploads screenshots as theios-simulator-screenshotsartifact.ios.yml: runs thebetalane (TestFlight) on everyv*tag. Manual runs also offerrelease(App Review submission with screenshots) andupload_screenshots(screenshots only, no submission). A manualbetarun accepts abeta_refbranch to build. The other lanes reject it. The workflow uses theapp-storeenvironment, which only allowsmainandv*tags. Screenshot runs keep the generated PNGs and the full bundles in theios-app-store-screenshotsartifact for 14 days.
Secrets and variables
These values belong to the app-store environment unless noted.
| Name | Kind | Used by |
|---|---|---|
MATCH_PASSWORD, MATCH_DEPLOY_KEY | Secret | match reads the certificate and profile from pipedash-certificates-v2 |
ASC_KEY_ID, ASC_ISSUER_ID, ASC_KEY_CONTENT | Secret | App Store Connect API key |
APPLE_TEAM_ID | Repository secret | Signing team |
APP_REVIEW_DEMO_TOKEN | Secret | release only: GitHub token for the demo repository, filled into the review notes |
APP_REVIEW_DEMO_REPOSITORY | Variable | release only: owner/repo of the demo repository |
PIPEDASH_PUSH_RELAY_URL | Optional repository variable | Cannot activate remote push or Watch in this build |
App Review demo access
release checks the configured GitHub demo before Apple authentication, signing or upload. It sends only authenticated GET requests. The repository must be public, active and writable by the user of the token. Public access lets reviewers open its GitHub page without a repository invitation. GitHub can still require a sign-in to read workflow logs in the browser.
The check finds an active workflow_dispatch workflow on the default branch with defaults for required inputs, a successful manual run and available jobs. It reads the first 100 workflows at most, which matches the workflow list of the app. It fills the name of that workflow into the review instructions.
An HTTP failure stops the release with the endpoint and permission guidance. A network failure omits raw exception details to protect credentials. The lane registers the token for secret masking and rejects --verbose, because the HTTP debug output of Fastlane can include request credentials.
Complete this checklist before each submission:
- Use a dedicated public demo repository. Keep production code, credentials, organization secrets, deployments and production network access out of its workflows.
- Create a fine-grained token with "Only select repositories" set to that repository. Grant Actions read/write and Contents read only. Do not use a production token or an unrestricted classic token. Set an expiry of at least 90 days, so the token stays valid through re-reviews and appeals.
releasechecks the token only when it runs, so an expired token later leaves App Review unable to add the demo provider. - Keep a harmless
workflow_dispatchworkflow on the default branch with defaults for any required inputs. Give it enough runtime to test "Stop workflow". Keep a successful manual run with jobs. - Test the review instructions on an iPhone or iPad. Cover provider setup, run details, browser logs, "Run workflow" > "Trigger" and "Stop workflow". The provider export must open the native Files picker and allow any destination.
- Answer the App Store Connect export compliance questions for the build. The app links rustls and ring for TLS and uses AES-256-GCM with Argon2id for password-encrypted credential storage.
ITSAppUsesNonExemptEncryptionisfalseinInfo.ios.plist, andverify_ipademands that value. Keep it only if the export classification shows that this use is exempt. Otherwise set it totrue, updateverify_ipaand upload any documentation that App Store Connect requests.
GitHub read endpoints cannot prove the repository restriction of the token, the Actions write permission or that the workflow is harmless. The permissions.push field of the repository reflects the permission of the user. It does not reflect the full permissions of the token. The preflight does not dispatch or cancel a workflow to test write access, so it does not replace the checklist.
Run locally
Run the checks on macOS:
cd ios
bundle install
bundle exec fastlane ios checkThe certificate and the profile expire on 2027-10-24. Renewing them runs match without readonly from the ios directory with the App Store Connect API key. The history of pipedash-certificates-v2 shows earlier renewals.
Signing prerequisites
The signed lanes use read-only match for com.henrique.pipedash only. The certificate repository must contain its App Store profile and the private key of the certificate. The app does not request the Push Notifications entitlement, and verify_ipa rejects an APNs entitlement in the signed app.
An authorized maintainer renews the app profile from macOS with writable access to the certificate repository:
cd ios
bundle exec fastlane match appstore --app_identifier com.henrique.pipedash --readonly falseThe command uses the existing authentication of the certificate repository and MATCH_PASSWORD. The Apple account or API key needs permission to manage identifiers and distribution profiles. The CI deploy key and the read-only match step do not create missing profiles.
Tauri archives the app with manual signing settings. Fastlane exports the archive with the provisioning profile mapping of the app. The build_app action requires export_method: "app-store". The Tauri CLI and the Xcode export_options[:method] value keep app-store-connect. verify_ipa checks the disabled-feature metadata and rejects bundled app extensions as part of its App Store checks.
Disabled build watching
The release build disables Watch, remote push and Live Activities. PipedashBuildWatchEnabled is false in crates/pipedash-desktop/Info.ios.plist. The native plugin rejects watch starts, skips background task registration and reports Watch as unsupported. The frontend hides the Watch and remote push controls. Existing snapshots stay stored and do not restart automatically.
The app declares no build-watch background task identifiers and no processing or remote-notification background modes. It declares only the com.henrique.pipedash.notifications-refresh task with the fetch mode, and verify_ipa requires exactly that. The app bundles no WidgetKit extension and no Live Activity support. verify_ipa rejects these capabilities and any enabled build-watch flag before upload.
A relay URL in the environment cannot activate either feature. Changing the flag alone is not a supported release configuration.
On upgrade, the native plugin dismisses custom activities that older versions left behind. It keeps their attribute type only for this cleanup. The disabled monitoring code uses iOS 26 APIs behind availability checks, so it does not change the iOS 15.0 minimum.
Remote push
Remote push uses the same PipedashBuildWatchEnabled flag. The app skips token synchronization and rejects the pairing, unpairing and test push commands before it reads saved settings or uses the network. The native plugin unregisters from remote notifications at app start and rejects registration without asking for notification permission.
Saved pairings stay on the device. Local notifications work independently and need no APNs entitlement. The push APIs of the server stay separate from this disabled iOS feature. The push relay page covers the server side.
Tests
Run the Ruby tests from the ios directory:
bundle exec ruby -e 'Dir["fastlane/*_test.rb"].sort.each { |file| require_relative file }'The ios-check.yml workflow runs this suite before the build. The App Review preflight cases run offline, without GitHub or Apple credentials:
bundle exec ruby fastlane/app_review_demo_test.rbThe screenshot tests use temporary files and replace the external Apple actions. They check the export failure gates, locale isolation, screenshot-only delivery and TestFlight isolation. The delivery checks exercise the Fastlane runner without authentication or upload.
App Store screenshots
The screenshot editor lives in ios/app-store-screenshots. It edits the English iPhone and iPad decks without changing the production app. Commit its project JSON and the source PNGs after the compositions get approval. release exports those saved compositions with their device mockups. It does not recapture the app and does not replace approved source images. The screenshot editor maintenance page covers headline alternatives, dependency upkeep and the editor tests.
Editor
The editor needs Node.js ^22.22.3 || >=24.8.0 and Bun. Run it from ios/app-store-screenshots:
bun install --frozen-lockfile
bun dev --hostname 127.0.0.1 --port 3000Open http://127.0.0.1:3000. Select iPhone or iPad, edit the copy or drag the device, and click "Export bundle". Each deck has 5 framed product captures and a feature-list closer. Changes save to app-store-screenshots.json. Keep that file and public/screenshots/ together.
Design rules
The customized midnight-glow-pro preset appears as "Pipedash Flat" in the editor. It follows the Pipedash design guide: system typography, solid surfaces, quiet separators and blue emphasis. The decks have no decorative beams, halos, textures or glass cards. The first 2 slides share a thin baseline across the connected canvas. Headlines and product content stay inside their own crops.
Palette values come from src/theme/index.ts and the iOS surface roles in src/App.css. The theme entry in ios/app-store-screenshots/src/lib/constants.ts holds the screenshot palette: the iOS cell background, gray foregrounds and blue shade 3 for text emphasis. Shade 7 is the accent on light backgrounds. Captured UI keeps the status tokens of the app.
The template supplies the physical iPhone and iPad bezels. Apple licenses those assets for Apple-platform app mockups. The Android and Mac decks stay empty.
Captures
The images show the real Pipedash frontend with synthetic repositories, runs, provider incidents and notifications. They are Chromium captures with iOS user agents, not native iOS simulator captures. They contain no real credentials or customer data. The capture script allows only a loopback app URL, blocks external HTTP requests and rejects unexpected API calls or mutations.
From the repository root, start the application frontend:
bun install --frozen-lockfile
bun run dev --host 127.0.0.1 --port 5198 --strictPortIn another terminal, from the repository root, run the capture script:
node ios/app-store-screenshots/scripts/capture-app.mjsThe script uses the Playwright dependency of the editor and /usr/bin/chromium. CHROMIUM_PATH selects another Chromium executable. CAPTURE_APP_URL accepts another loopback frontend URL. The script checks the output dimensions, the populated workflow inputs, unexpected requests and page errors.
Captures live in public/screenshots/apple/{iphone|ipad}/en/01.png through 05.png, in this order:
- Unified pipelines across GitHub, GitLab, Jenkins and Argo CD.
- Workflow execution with release parameters.
- Failed workflow and run history.
- Provider health and an incident from its status page.
- Failure, outage and recovery notifications.
Reload the editor after a recapture, so it reads the updated images. The source sizes are 1320x2868 for iPhone and 2064x2752 for iPad.
Exports and sizes
The exports/ directory contains the generated bundles and thumbnail previews. Git ignores it, because the editor can regenerate it.
| Deck | Slides | Export sizes | PNGs |
|---|---|---|---|
| iPhone | 6 | 1320x2868, 1284x2778, 1206x2622, 1125x2436 | 24 |
| iPad | 6 | 2064x2752, 2048x2732 | 12 |
bun run typecheck and bun run build check the editor. bun run test:export-fastlane runs the export edge tests. The export checks cover exact dimensions, opaque RGB pixels and solid corner pixels.
Browser captures do not show the native system bars or the WebKit rendering. Compare them with the shipped app and check the final files in App Store Connect before submitting.
Publishing with Fastlane
From ios, bundle exec fastlane ios prepare_screenshots builds the editor and exports both saved decks without Apple credentials. It installs Playwright Chromium unless CHROMIUM_PATH points to an existing browser. On Linux, CHROMIUM_PATH=/usr/bin/chromium bundle exec fastlane ios prepare_screenshots uses the installed browser.
The script drives the export through the same editor controls. Autosaves stay in browser memory. The validation checks that the canonical JSON stays unchanged and that both decks are complete before it replaces fastlane/screenshots/en-US/. Supported decks use English, portrait orientation and 1 to 10 slides each. Preparation rejects extra directories in the upload folder instead of sending them.
The upload directory holds one size per device, 1320x2868 for iPhone and 2064x2752 for iPad. Uploading both exported iPad sizes would put 12 images into one Fastlane device slot, which is above the Apple limit of 10 images. The complete multi-size bundles stay in app-store-screenshots/exports/.
To update only the screenshots on the existing editable iOS version, run:
bundle exec fastlane ios upload_screenshotsThis lane needs ASC_KEY_ID, ASC_ISSUER_ID and ASC_KEY_CONTENT. It needs no signing or match credentials. It skips the binary, the metadata, the version update and the review submission.
release includes the same images in the App Store submission flow, and beta leaves App Store screenshots alone. Both publishing lanes replace all existing screenshot sets for en-US and leave other locales unchanged. A failed export stops either lane before Apple authentication or upload. The existing screenshots lane remains the native simulator first-start check.
Push relay
The Pipedash push relay that forwards failed-pipeline alerts to APNs. Covers the APNs key, configuration, Docker, the relay API, limits and data retention.
Screenshot editor maintenance
Maintainer notes for the App Store screenshot editor. Covers headline alternatives, dependency upkeep, the end-to-end test suite, its flow matrix and its limits.