Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
119 commits
Select commit Hold shift + click to select a range
c7a0512
feat(mobile): add the native posthog triage app
cvolzer3 Oct 16, 2026
fb2a704
Merge commit 'cd3e77c84bcc0166cf8a90ebcc5a1ac35597c146' into codex/mo…
cvolzer3 Oct 16, 2026
a42a9b0
fix(mobile): align chat icon and include API types in CI
cvolzer3 Oct 16, 2026
49b4316
chore(mobile): align dependency trust settings with the repo
cvolzer3 Oct 16, 2026
c9b14d7
chore(mobile): wire generated types into repository checks
cvolzer3 Oct 16, 2026
de36488
chore(mobile): collect verified Xcode recovery instructions
cvolzer3 Oct 16, 2026
eaf0428
fix(mobile): address review feedback on sessions and views
cvolzer3 Oct 16, 2026
3f1003f
chore(mobile): merge master before publishing review fixes
cvolzer3 Oct 16, 2026
cc7da54
fix(mobile): center sign-in content and anchor legal links
cvolzer3 Oct 16, 2026
dbdc889
chore(mobile): merge master before publishing sign-in layout
cvolzer3 Oct 16, 2026
7a9bdcf
fix(mobile): use pin buttons instead of view swipes
cvolzer3 Oct 16, 2026
7b8200b
chore(mobile): merge master before views pin update
cvolzer3 Oct 16, 2026
3485ab0
fix(mobile): make the default chat model clearly selected
cvolzer3 Oct 16, 2026
3fc4541
chore(mobile): sync master and model selection docs
cvolzer3 Oct 16, 2026
216a228
fix(mobile): show feedback for every views refresh
cvolzer3 Oct 16, 2026
5a1568a
fix(mobile): leave scout runs out of the Chats list
cvolzer3 Oct 16, 2026
b6156d8
fix(mobile): preserve saved dashboard value formatting
cvolzer3 Oct 16, 2026
ec9925a
chore(mobile): sync master before pushing formatting fix
cvolzer3 Oct 16, 2026
6038cdb
fix(mobile): align search field text across tabs
cvolzer3 Oct 16, 2026
6009d89
chore(mobile): sync master for search alignment fix
cvolzer3 Oct 16, 2026
c8bb6bb
fix(mobile): render thoughts as markdown and name PostHog tool calls
cvolzer3 Oct 16, 2026
7b834e7
feat(mobile): queue and steer messages while the agent works
cvolzer3 Oct 16, 2026
b8f3abd
feat(mobile): draw SQL insights as tables, charts and bars
cvolzer3 Oct 16, 2026
7093674
feat(mobile): attach files in chat
cvolzer3 Oct 16, 2026
04ee61b
feat(mobile): add chat archiving and store demo access
cvolzer3 Oct 16, 2026
351c82e
chore(mobile): sync master for chat archiving and demo access
cvolzer3 Oct 16, 2026
b0b829a
fix(mobile): restore the chat list when undo fails
cvolzer3 Oct 16, 2026
6bd82b0
fix(mobile): fit pinned number cards to their content
cvolzer3 Oct 16, 2026
b775014
chore(mobile): sync master before the spacing fix release
cvolzer3 Oct 16, 2026
f09c675
fix(mobile): start chat activity rows closed
cvolzer3 Oct 19, 2026
e24a77a
feat(mobile): filter and sort the inbox, drop the header refresh button
cvolzer3 Oct 19, 2026
d44d8ff
fix(mobile): upload chat attachments through expo/fetch
cvolzer3 Oct 19, 2026
4a47b8c
feat(mobile): choose the page the app opens on
cvolzer3 Oct 19, 2026
f6700ec
feat(mobile): default the start page to views when ai is not approved
cvolzer3 Oct 19, 2026
c28b147
feat(mobile): show tab icons on the start page options
cvolzer3 Oct 19, 2026
157cde3
fix(mobile): hide the duplicate settings title on android
cvolzer3 Oct 19, 2026
53f17d2
chore(mobile): sync master for the android title fix
cvolzer3 Oct 19, 2026
a6ff20f
feat(mobile): configure the new google play app identity
cvolzer3 Oct 19, 2026
718ce9e
chore: merge master into codex/mobile-app
cvolzer3 Oct 19, 2026
31e6a33
chore(mobile): sync release branch with master
cvolzer3 Oct 20, 2026
afa3d6a
fix(mobile): use the reports list for the personal inbox
cvolzer3 Oct 20, 2026
2db1a27
Merge remote-tracking branch 'origin/master' into codex/remove-sleepi…
cvolzer3 Oct 20, 2026
b8d403a
fix(mobile): remove the sleeping widget hedgehog
cvolzer3 Oct 20, 2026
51cc1a0
fix(mobile): address state races and chart correctness
cvolzer3 Oct 20, 2026
73b9085
chore(mobile): bump native update runtime to 1.2.1
cvolzer3 Oct 20, 2026
ef92d11
chore(mobile): sync release branch before Android build
cvolzer3 Oct 20, 2026
a735e26
chore(mobile): sync frontend branch with master
cvolzer3 Oct 20, 2026
d5ef9f4
Merge remote-tracking branch 'origin/master' into codex/mobile-notifi…
cvolzer3 Oct 20, 2026
104ac7d
feat(mobile): show useful visuals within pinned views
cvolzer3 Oct 20, 2026
6aabb3d
feat(mobile): customize push notifications and chat routing
cvolzer3 Oct 20, 2026
8dc5196
Merge remote-tracking branch 'origin/codex/mobile-app' into codex/mob…
cvolzer3 Oct 20, 2026
48bc461
Merge remote-tracking branch 'origin/master' into codex/mobile-notifi…
cvolzer3 Oct 20, 2026
d841fb1
feat(mobile): hint that a pinned view has a long-press menu
cvolzer3 Oct 20, 2026
4927db2
feat(mobile): open the full report from the report screen
cvolzer3 Oct 21, 2026
8b050fd
feat(mobile): follow the device's light or dark appearance
cvolzer3 Oct 21, 2026
b3d91a9
feat(mobile): add an appearance setting to override the device scheme
cvolzer3 Oct 21, 2026
510414e
fix(mobile): wrap long chat input across multiple lines
cvolzer3 Oct 22, 2026
55c8814
chore(mobile): sync master before chat input update
cvolzer3 Oct 22, 2026
9932fd6
fix(mobile): preserve default model selection after sending
cvolzer3 Oct 22, 2026
384bb0c
chore(mobile): merge master into app branch
cvolzer3 Oct 22, 2026
3f12322
chore(mobile): sync generated object tag routes with master
cvolzer3 Oct 22, 2026
456dd0a
chore(mobile): merge latest app branch updates
cvolzer3 Oct 22, 2026
e28f80d
fix(mobile): reuse open chats when handling notifications
cvolzer3 Oct 23, 2026
ec94efc
chore(mobile): sync master before chat navigation update
cvolzer3 Oct 23, 2026
32171d2
feat(mobile): errors and session replay on the phone
cvolzer3 Oct 23, 2026
100e369
Merge remote-tracking branch 'origin/codex/mobile-app' into chris/mob…
cvolzer3 Oct 23, 2026
7b55ad7
chore(mobile): prepare 1.3.0 testing release
cvolzer3 Oct 23, 2026
c945692
feat(mobile): download ota updates and gate sessions and errors
cvolzer3 Oct 23, 2026
58a43c1
chore(mobile): sync master before ota and release controls
cvolzer3 Oct 23, 2026
0208b60
chore(mobile): document shared release checks
cvolzer3 Oct 26, 2026
33b7575
feat(mobile): gate ai actions on current organization approval
cvolzer3 Oct 26, 2026
69a51fd
feat(mobile): publish reviewed release requests from ci
cvolzer3 Oct 26, 2026
49f78e2
chore(mobile): sync master for release documentation
cvolzer3 Oct 26, 2026
1097d8b
chore(mobile): reconcile hosted release documentation
cvolzer3 Oct 26, 2026
32649da
chore(mobile): record native smoke test timings
cvolzer3 Oct 26, 2026
60cee3a
chore(mobile): preserve release checklist during rebase
cvolzer3 Oct 26, 2026
6368582
feat(mobile): animate splash and refresh logomarks
cvolzer3 Oct 26, 2026
5e565df
fix(mobile): preserve native splash configuration for ota
cvolzer3 Oct 26, 2026
4996ba5
chore(mobile): prepare 1.4.0 native release
cvolzer3 Oct 26, 2026
5cf88aa
fix(mobile): match errors and sessions title spacing to settings
cvolzer3 Oct 26, 2026
a72d7ea
Merge remote-tracking branch 'origin/master' into codex/mobile-app
cvolzer3 Oct 26, 2026
80054b8
chore(mobile): advance initial hosted release baseline
cvolzer3 Oct 26, 2026
0e47f1a
fix(mobile): unify page spacing and fade centered scroll titles
cvolzer3 Oct 26, 2026
c2362a4
Merge remote-tracking branch 'origin/master' into codex/mobile-app
cvolzer3 Oct 26, 2026
6c05e36
fix(mobile): allow immediate manual view refresh
cvolzer3 Oct 26, 2026
6c60f69
chore(mobile): require Mobile CI and move demo flows local
cvolzer3 Oct 26, 2026
16ebc06
fix(mobile): reduce initial sessions and errors loading
cvolzer3 Oct 26, 2026
234f7f3
chore(mobile): sync master after pagination update
cvolzer3 Oct 26, 2026
fb3ff3b
fix(mobile): remove notification preferences footer
cvolzer3 Oct 27, 2026
0dfca44
chore(mobile): sync master before footer cleanup push
cvolzer3 Oct 27, 2026
b51fac0
chore(ci): clarify mobile build concurrency comment
cvolzer3 Oct 27, 2026
33905a4
chore(mobile): narrow root formatter exclusions
cvolzer3 Oct 27, 2026
6efae61
chore: merge master into mobile app
cvolzer3 Oct 27, 2026
168b0e2
chore(ci): remove redundant expo secret setup comment
cvolzer3 Oct 27, 2026
3faa3f0
fix(mobile): collapse empty pinned card footer space
cvolzer3 Oct 27, 2026
9b97f44
chore: merge master into mobile app
cvolzer3 Oct 27, 2026
d3e3e0c
fix(mobile): show complete pinned charts and correct ranges
cvolzer3 Oct 27, 2026
ea22807
fix(mobile): hide dashboard ranges when no charts follow them
cvolzer3 Oct 27, 2026
f4bd948
fix(mobile): simplify the date range filter
cvolzer3 Oct 27, 2026
79b82d2
chore(mobile): merge master into mobile app
cvolzer3 Oct 27, 2026
d799384
chore(mobile): integrate mobile app branch updates
cvolzer3 Oct 27, 2026
f9ef284
chore(mobile): sync latest master before push
cvolzer3 Oct 27, 2026
74b1ab9
feat(mobile): collapse long project lists in settings
cvolzer3 Oct 27, 2026
2db6301
fix(mobile): protect releases and account privacy
cvolzer3 Oct 27, 2026
99a45d6
chore(mobile): sync master before security fixes
cvolzer3 Oct 27, 2026
6ab58ff
chore(mobile): merge current master
cvolzer3 Oct 28, 2026
a17c9fb
fix(mobile): make local development reliable
cvolzer3 Oct 28, 2026
e3a3a68
Merge remote-tracking branch 'origin/master' into codex/mobile-app
cvolzer3 Oct 28, 2026
00d0956
chore(mobile): make release tests portable on linux
cvolzer3 Oct 28, 2026
aaccfa5
chore(mobile): provision public ota signing certificate
cvolzer3 Oct 28, 2026
0faa3fb
Merge remote-tracking branch 'origin/master' into codex/mobile-app
cvolzer3 Oct 28, 2026
980197e
chore(mobile): address workflow review feedback
cvolzer3 Oct 29, 2026
5275d74
chore(mobile): sync workflow fixes with master
cvolzer3 Oct 29, 2026
96ea3c6
chore(mobile): use fallback token for dependabot checks
cvolzer3 Oct 29, 2026
8f6bd1c
fix(mobile): preserve session and approval boundaries
cvolzer3 Oct 29, 2026
7d7dee3
chore(mobile): sync security fixes with master
cvolzer3 Oct 29, 2026
eb830f8
Merge branch 'master' into codex/mobile-app
cvolzer3 Oct 29, 2026
53c3b97
chore(mobile): sync app branch with master
cvolzer3 Oct 29, 2026
aa005cd
feat(mobile): simplify login and select a default region
cvolzer3 Oct 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
108 changes: 108 additions & 0 deletions .agents/skills/requesting-mobile-releases/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
---
name: requesting-mobile-releases
description: >
Decides whether a PostHog mobile app change can ship as an over-the-air (OTA) update or needs a native
store release, then creates the release request file under products/mobile/releases/requests/. Use
before creating or editing a mobile release request, when asked to ship, release, publish or push an
update of the mobile app, and when a change under products/mobile touches package.json,
pnpm-lock.yaml, app.config.ts, eas.json, plugins/, targets/, modules/ or any expo-* or react-native-*
dependency. Covers the native fingerprint comparison, the version rule, and what the request must say.
---

# Requesting mobile releases

A merged release request is the release trigger.
Mobile Release publishes it from `master` with no human gate.
An `ota` request goes straight to the production channel that installed apps pull from.
A `native` request submits both binaries to TestFlight and Play internal testing.
Decide the kind before you create the file, and say which kind you chose and why in the PR description.

[RELEASING.md](../../../products/mobile/docs/RELEASING.md) has the commands and the recovery procedure.
[OTA.md](../../../products/mobile/docs/OTA.md) has the runtime rules.
This skill is the decision procedure.

## 1. Classify the change

An OTA update replaces JavaScript and assets only.
The installed binary keeps its native code, so anything the native fingerprint covers forces a native release.
A change needs `native` when it touches any of:

- a dependency with native code: most `expo-*`, `react-native-*` and `@react-native-*` packages, `@shopify/react-native-skia`, and anything that ships `ios/` or `android/` directories in `node_modules`;
- `app.config.ts` fields under `ios`, `android`, `plugins`, `runtimeVersion` or `version`, and icons, splash, entitlements or permissions;
- `plugins/`, `targets/` (widgets), `modules/` (local native modules), or the build profiles in `eas.json`;
- the Expo SDK or React Native version;
- a `pnpm-lock.yaml` change that adds or bumps any of the above, also transitively.

Changes limited to `src/`, `app/` routes, assets, copy and fixtures are OTA candidates.

Quick scan from `products/mobile`:

```sh
git diff origin/master --stat -- package.json pnpm-lock.yaml app.config.ts eas.json plugins targets modules
```

An empty result means the change is probably OTA-safe.
A non-empty result does not make it native by itself. Run step 2 either way.

## 2. Confirm with the fingerprint

`pnpm release:fingerprint` prints the iOS and Android native fingerprints of the checkout, computed the same way the publisher computes them.
Compare the branch against the commit of the last completed native release:

```sh
# Find the last completed release and its native baseline commit.
TAG_SHA=$(gh api repos/PostHog/posthog/git/ref/tags/mobile-production -q .object.sha)
LAST_ID=$(gh api "repos/PostHog/posthog/git/tags/$TAG_SHA" -q .message | jq -r .id)
BASE=$(gh release view "mobile-release/$LAST_ID" --repo PostHog/posthog --json body -q .body | jq -r .native.commit)

# Head: in the branch, from products/mobile.
pnpm install --frozen-lockfile && pnpm release:fingerprint > /tmp/fp-head.json

# Base: a disposable worktree at the baseline commit.
git worktree add --detach /tmp/mobile-fp-base "$BASE"
(cd /tmp/mobile-fp-base/products/mobile && pnpm install --frozen-lockfile && pnpm release:fingerprint > /tmp/fp-base.json)
git worktree remove --force /tmp/mobile-fp-base

diff /tmp/fp-base.json /tmp/fp-head.json
```

Before the first hosted native release there is no `mobile-production` tag. Compare against `origin/master` instead, and remember that the first hosted release must be `native`.

- Identical fingerprints: the change can ship as `ota`.
- Any difference: request `native` and raise `version` in `app.config.ts`.

Compute both sides on the same machine.
Locally neither side has the EAS production environment (`GOOGLE_SERVICES_JSON`, `APPLE_TEAM_ID`), so a local fingerprint never matches the one in a receipt, but a local base-to-head comparison is valid.
The publisher repeats the comparison with the real environment after the merge and refuses an incompatible OTA. Catch it here, before the PR merges.

## 3. Apply the version rule

- `ota`: keep `version` in `app.config.ts` equal to the runtime of the last native release.
- `native`: raise `version` above it. Build numbers come from EAS (`autoIncrement`); do not set them by hand.

`pnpm release:check` enforces this against the PR base in CI.

## 4. Create the request

From `products/mobile`, with `LAST_ID` from step 2 as the predecessor:

```sh
pnpm release:request ota --id <lowercase-id> --previous "$LAST_ID" --notes "What testers should verify."
pnpm release:request native --id native-<version-digits> --previous "$LAST_ID" --notes "What changed natively."
pnpm release:check
pnpm release:test
```

Rules the publisher enforces:

- One new request per PR. A push that adds two fails.
- Requests are append-only. Never edit, rename or delete a merged request.
- Commit the request with the app change it releases.
- The notes become the body of a public GitHub prerelease. Keep customer names, credentials and internal links out of them.

Run `/running-mobile-demo-flows` on the same branch before you open the PR.

## 5. Report

State the kind, the fingerprint result per platform, the predecessor id, and the app version.
If you could not run the fingerprint comparison, say so and do not create an `ota` request.
79 changes: 79 additions & 0 deletions .agents/skills/running-mobile-demo-flows/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
name: running-mobile-demo-flows
description: >
Runs the PostHog mobile app's Argent demo flows (demo-smoke and views-smoke) on a local iOS simulator
against a bundled Release build, and reads their results. Use before reporting a change under
products/mobile that touches a screen, navigation, the demo fixtures, a testID, or a flow file as done,
and when asked to smoke-test the mobile app. CI does not run these flows, so the local run is the only
UI check a change gets.
---

# Running mobile demo flows

The flows live in `products/mobile/.argent/flows/`.
`demo-smoke` walks the inbox, a report, the hand-off sheet, decisions and chat in demo mode.
`views-smoke` covers the Views tab.
Both start and end on the sign-in screen with demo mode off, so a run can repeat right away.
[TESTING.md](../../../products/mobile/docs/TESTING.md#demo-walkthrough-on-the-ios-simulator) lists each step.

## When to run them

- A change under `products/mobile/app/`, `src/features/`, `src/ui/`, navigation, or the demo fixtures.
- A change to a flow YAML or to a `testID` the flows use.
- Before you create a release request (see `/requesting-mobile-releases`).

Skip them for a change that only touches docs, tests, backend code, or build configuration.

## Prerequisites, once per machine

- Xcode with an iOS simulator runtime, and CocoaPods. The scripts are verified on Xcode 26.6 with iOS 26.5 and on Xcode 27.1 with iOS 27.0.
- Argent 0.30.1 in a private prefix, so it does not collide with an editor's Argent server:

```sh
DO_NOT_TRACK=1 npm install --prefix /tmp/mobile-argent-tools --no-audit --no-fund @swmansion/argent@0.30.1
```

## Run the bundled flows

From `products/mobile`:

```sh
export PATH="/tmp/mobile-argent-tools/node_modules/.bin:$PATH"
export DO_NOT_TRACK=1
pnpm install --frozen-lockfile
bash scripts/ci-argent-build.sh /tmp/mobile-argent-build /tmp/mobile-argent-artifacts
bash scripts/ci-argent.sh \
/tmp/mobile-argent-build/Build/Products/Release-iphonesimulator/PostHog.app \
/tmp/mobile-argent-artifacts
```

Budget about 8 minutes for a fresh native build and about 3 minutes for both flows.
The build regenerates the ignored `ios/` directory, so use a disposable worktree when the checkout has manual native edits.
The flow script creates its own temporary simulator, so other booted simulators do not interfere.
Set `ARGENT_IOS_RUNTIME` to a runtime id from `xcrun simctl list runtimes` to pick another installed runtime.

## Read the result

- Exit code 0 means both flows passed.
- On failure, open `/tmp/mobile-argent-artifacts/`: the JSON report has one entry per step, failed steps have a screenshot, and `prebuild.log`, `pods.log` and `build.log` explain a native build failure.
- Both flows run even when the first fails. Report each one.
- An `idle` step can warn that a small part of the screen was still changing, such as the text caret. The next step waits for a stable element, so this warning is expected.

## Iterate on a flow with the dev client

The bundled build is slow to rebuild. While you edit a flow or a screen, use Metro instead:

1. `pnpm ios --port 8181` builds the dev client, boots a simulator and starts Metro.
2. In the dev menu, turn off **Tools button** and **Fast refresh**. The floating gear swallows taps on the inbox More button, and the refresh banner covers Back and Close.
3. Make sure demo mode is off (Settings, **Exit demo**).
4. `argent flow run demo-smoke --platform ios` from `products/mobile`. Add `--device <udid>` when more than one simulator is booted.

Known traps: a system "Open in PostHog?" alert after a deep link is invisible to Argent selectors, so dismiss it with a raw tap.
If every selector step times out with a ViewInspector RPC error, drive by normalized coordinates and screenshots instead.
[TESTING.md](../../../products/mobile/docs/TESTING.md#troubleshooting) has the rest.

## Report

State which flows ran, the Xcode and runtime versions, and pass or fail per flow.
Name the failed step and its screenshot path when one failed.
Do not commit `.argent/recordings/` or the artifact directory.
5 changes: 5 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,8 @@ products/isolation_baseline.txt @PostHog/team-devex
/CLAUDE.md @PostHog/team-devex
.github/pull_request_template.md @PostHog/team-devex
.agents/skills/writing-pr-descriptions/ @PostHog/team-devex

# The mobile owner reviews app changes and the workflows that build and release it.
products/mobile/** @cvolzer3

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 Mobile release policy, signing trust root, and credential-bearing workflows lose team-security review

This delta replaces the prior entries that put products/mobile/releases/** (release requests and the OTA signing certificate that authorize code on installed devices), products/mobile/scripts/releases/** (release.mjs/policy.mjs validation), and mobile-release.yml/mobile-build.yml (which handle MOBILE_OTA_SIGNING_KEY and MOBILE_PRODUCTION_EXPO_TOKEN, line 98's glob .github/workflows/*mobile*.yml @cvolzer3) under @PostHog/team-security, with sole ownership by one individual. The deleted comment stated the exact risk: "A merged mobile release request authorizes code on installed devices. Keep its policy, signing trust root and credential-bearing workflows under the same review."

How:

  1. After this merges, open a PR editing products/mobile/releases/ota-certificate.pem, scripts/releases/policy.mjs, or mobile-release.yml.
  2. Only @cvolzer3's approval is required — no security review.
  3. A merged release request then publishes code to installed devices under the modified trust root or policy.

CODEOWNERS @PostHog/team-security still gates this one change, but every future change to those paths loses the gate.

Fix: restore @PostHog/team-security as a co-owner of products/mobile/releases/**, products/mobile/scripts/releases/**, and the mobile release/build workflows.


React with 👍 if useful or 👎 if not

products/desktop/apps/mobile/** @cvolzer3
.github/workflows/*mobile*.yml @cvolzer3
4 changes: 4 additions & 0 deletions .github/workflows/ci-python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,16 @@ jobs:
- 'products/desktop/packages/core/src/inbox/objectKinds.generated.ts'
- 'packages/agent/packages/agent-contracts/src/objectTagKinds.generated.ts'
- 'frontend/src/lib/components/AgentObjectTags/objectKinds.generated.ts'
- 'products/mobile/src/features/chat/objectKinds.generated.ts'
- 'products/tasks/frontend/modelCatalog.generated.ts'
- 'packages/agent/packages/agent-contracts/src/model-catalog.generated.ts'
- 'services/mcp/src/lib/oauth-scopes.generated.ts'
- 'frontend/src/lib/oauthScopes.generated.ts'
- 'products/commands/commands.generated.json'
- 'products/commands/COMMANDS.generated.md'
# Formatter inputs can change the generated mobile projection.
- 'products/mobile/biome.json'
- 'products/mobile/pnpm-lock.yaml'
# hogli CLI changes need validation
- 'tools/hogli/**'
- 'tools/hogli-commands/hogli_commands/**'
Expand Down
115 changes: 115 additions & 0 deletions .github/workflows/mobile-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
name: Mobile Build

# Queues internal development/preview builds. Production binaries and OTA updates
# are published only by Mobile Release after a release request merges to master.
# Release steps: products/mobile/docs/RELEASING.md.
#
# Store credentials stay on EAS, set once with `eas credentials`, so this workflow
# never handles an Apple or Google key.

on:
# Manual only. A pull request run executes code its author controls, so it must
# never reach the Expo token or the stores.
workflow_dispatch:
inputs:
profile:
description: 'EAS build profile'
type: choice
default: preview
options:
- development
- preview
platform:
description: 'Platform'
type: choice
default: all
options:
- all
- ios
- android

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ inputs.profile }}-${{ inputs.platform }}
# Let an explicit build dispatch finish uploading and submitting to EAS.
# This only serializes GitHub runs in this group. With --no-wait, EAS builds
# continue independently and may overlap.
cancel-in-progress: false

permissions:
contents: read

jobs:
build:
if: github.repository == 'PostHog/posthog' && github.ref == 'refs/heads/master'
environment: mobile-build
name: EAS build (${{ inputs.profile }}, ${{ inputs.platform }})
runs-on: depot-ubuntu-24.04
timeout-minutes: 20
defaults:
run:
working-directory: products/mobile
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ github.sha }}
persist-credentials: false
sparse-checkout: products/mobile
sparse-checkout-cone-mode: false

- name: Setup pnpm
uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
with:
package_json_file: products/mobile/package.json
env:
# See mobile-ci.yml: a stalled npm audit or fetch otherwise waits 300s.
NPM_CONFIG_FETCH_TIMEOUT: 45000
NPM_CONFIG_FETCH_RETRIES: 2
NPM_CONFIG_AUDIT: 'false'
NPM_CONFIG_FUND: 'false'

- name: Setup Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version-file: products/mobile/.node-version
token: ${{ github.token }}

- name: Get pnpm store path
id: pnpm-store
run: echo "path=$(pnpm store path --silent)" >> "$GITHUB_OUTPUT"

# Same key as mobile-ci.yml, which writes it on master. Restore only.
- name: Restore pnpm store
uses: actions/cache/restore@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: ${{ steps.pnpm-store.outputs.path }}
key: mobile-pnpm-${{ runner.os }}-${{ hashFiles('products/mobile/pnpm-lock.yaml') }}
restore-keys: mobile-pnpm-${{ runner.os }}-

# EAS CLI evaluates app.config.ts and its config plugins, which need the
# app's dependencies on disk.
- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Setup EAS
uses: expo/expo-github-action@eab7a230208c952974db8c3245cfd78402c7b385 # 9.0.0
with:
# Pinned so a new eas-cli release cannot change a release build unannounced.
eas-version: 24.8.0
token: ${{ secrets.MOBILE_BUILD_EXPO_TOKEN }}

- name: EAS internal build
env:
PLATFORM: ${{ inputs.platform }}
PROFILE: ${{ inputs.profile }}
run: |
if [[ "$PROFILE" != "development" && "$PROFILE" != "preview" ]]; then
echo "::error::Use a merged mobile release request for production builds."
exit 1
fi
sh scripts/eas-build.sh \
--non-interactive \
--no-wait \
--platform "$PLATFORM" \
--profile "$PROFILE" \
--message "${GITHUB_REF_NAME}@${GITHUB_SHA::12}"
Loading
Loading