Skip to content

Commit 3e53cc1

Browse files
Merge posthog-code/finalize-mobile-portability-boundary
Generated-By: PostHog Code Task-Id: c1bbe3cf-742b-4b24-bf96-d11a18b4cf22
2 parents b5e5c1c + f188829 commit 3e53cc1

509 files changed

Lines changed: 27584 additions & 8681 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/skills/storybook-stories/SKILL.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
---
22
name: storybook-stories
3-
description: Write Storybook stories for PostHog Code UI components. Covers the provider stack stories run inside, the key gotcha that tRPC/useHostTRPC queries never resolve in Storybook (so data-fetching components render empty), and the pure-presentational split that makes a component storyable. Use when adding or fixing a *.stories.tsx file under packages/ui.
3+
description: Write Storybook stories for PostHog UI components. Covers the provider stack stories run inside, the key gotcha that tRPC/useHostTRPC queries never resolve in Storybook (so data-fetching components render empty), and the pure-presentational split that makes a component storyable. Use when adding or fixing a *.stories.tsx file under packages/ui.
44
---
55

6-
# Storybook stories in PostHog Code
6+
# Storybook stories in PostHog
77

88
Stories live next to components as `*.stories.tsx` and are collected by
99
`apps/code/.storybook/main.ts` (its glob includes

.claude/skills/test-electron-app/SKILL.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
---
22
name: test-electron-app
3-
description: Drive the real running PostHog Code Electron app (live tRPC, workspace-server, real data) over CDP with agent-browser. Connect to the running app on port 9222, snapshot the accessibility tree to verify changes, click/type/navigate, and screenshot the actual desktop app only when explicitly asked. Use when asked to test, verify, dogfood, screenshot or interact with the running app. For regression specs use the Playwright E2E suite.
3+
description: Drive the real running PostHog Electron app (live tRPC, workspace-server, real data) over CDP with agent-browser. Connect to the running app on port 9222, snapshot the accessibility tree to verify changes, click/type/navigate, and screenshot the actual desktop app only when explicitly asked. Use when asked to test, verify, dogfood, screenshot or interact with the running app. For regression specs use the Playwright E2E suite.
44
allowed-tools: Bash(agent-browser:*), Bash(npx agent-browser:*), Bash(pnpm app:cdp*)
55
---
66

7-
# Test the real PostHog Code Electron app
7+
# Test the real PostHog Electron app
88

99
Drive the actual running app over the Chrome DevTools Protocol with
1010
[agent-browser](https://github.com/vercel-labs/agent-browser). The dev app
@@ -186,7 +186,7 @@ When the user asked for a screenshot, they want to look at it, so close the loop
186186
default debugging port; if `connect` attaches to the wrong target, list and
187187
pick the PostHog window: `agent-browser tab` then `agent-browser tab --url "*"`.
188188
- **Multiple targets:** the app has a main renderer window (page title contains
189-
"PostHog Code") plus possible webviews/devtools. `agent-browser tab` lists them;
189+
"PostHog") plus possible webviews/devtools. `agent-browser tab` lists them;
190190
switch with `agent-browser tab <index>`.
191191
- **Never pass `--color-scheme dark`:** that global flag makes agent-browser apply
192192
device emulation that forces a 1280x720 viewport and renders this Electron window
@@ -201,7 +201,7 @@ When the user asked for a screenshot, they want to look at it, so close the loop
201201

202202
## Running alongside prod
203203

204-
PostHog Code orchestrates the agent, so the usual loop is: **prod** (the installed app) runs the agent, and the **dev** build (`pnpm dev`) is the system under test. They coexist by design (`apps/code/src/main/bootstrap.ts`): dev runs as `posthog-code-dev` with its own app name, userData and single-instance lock, so it never collides with prod.
204+
PostHog orchestrates the agent, so the usual loop is: **prod** (the installed app) runs the agent, and the **dev** build (`pnpm dev`) is the system under test. They coexist by design (`apps/code/src/main/bootstrap.ts`): dev runs as `posthog-code-dev` with its own app name, userData and single-instance lock, so it never collides with prod.
205205

206206
- **agent-browser always targets dev.** Only the dev build exposes CDP on `:9222`; prod has no debug port, so `connect 9222` can't accidentally drive prod.
207207
- **Separate auth/state.** The dev instance has its own `posthog-code-dev` profile; it is not signed in just because prod is. Sign into the dev window once; its state persists.
@@ -220,6 +220,6 @@ PostHog Code orchestrates the agent, so the usual loop is: **prod** (the install
220220
check the `pnpm dev:code` output. Note `pnpm dev` cannot run headlessly at all — its
221221
`phrocs` TUI needs a TTY; use `pnpm dev:code`.
222222
- **Snapshot is empty / wrong window:** you're on the wrong target. Run
223-
`agent-browser tab` and switch to the "PostHog Code" page.
223+
`agent-browser tab` and switch to the "PostHog" page.
224224
- **Can't type into an input:** try `agent-browser keyboard type "text"` (types at
225225
current focus) or `agent-browser keyboard inserttext "text"` to bypass key events.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
name: Restore turbo cache
2+
description: Restore-only turbo cache. warm-caches.yml seeds it on main pushes; PR workflows never save, so per-PR entries don't pollute the cache store.
3+
4+
runs:
5+
using: composite
6+
steps:
7+
- name: Restore turbo cache
8+
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
9+
with:
10+
path: .turbo/cache
11+
key: turbo-${{ github.sha }}
12+
restore-keys: |
13+
turbo-

.github/workflows/build.yml

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -59,29 +59,17 @@ jobs:
5959
node-version: 22
6060
cache: "pnpm"
6161

62+
- name: Restore turbo cache
63+
uses: ./.github/actions/restore-turbo-cache
64+
6265
- name: Install dependencies
6366
run: pnpm install --frozen-lockfile
67+
env:
68+
# The packaged app is never launched, so the Electron-ABI rebuild is unused.
69+
SKIP_ELECTRON_REBUILD: "1"
6470

65-
- name: Build electron-trpc
66-
run: pnpm --filter @posthog/electron-trpc build
67-
68-
- name: Build platform
69-
run: pnpm --filter @posthog/platform build
70-
71-
- name: Build shared
72-
run: pnpm --filter @posthog/shared build
73-
74-
- name: Build git
75-
run: pnpm --filter @posthog/git build
76-
77-
- name: Build enricher
78-
run: pnpm --filter @posthog/enricher build
79-
80-
- name: Build harness
81-
run: pnpm --filter @posthog/harness build
82-
83-
- name: Build agent
84-
run: pnpm --filter agent build
71+
- name: Build packages
72+
run: pnpm run build:deps
8573

8674
- name: Build code
8775
run: pnpm --filter code build

.github/workflows/code-build-test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,9 @@ jobs:
114114
MATRIX_ARCH: ${{ matrix.arch }}
115115
run: |
116116
if [[ "$MATRIX_ARCH" == "arm64" ]]; then
117-
APP_BUNDLE="apps/code/out/mac-arm64/PostHog Code.app"
117+
APP_BUNDLE="apps/code/out/mac-arm64/PostHog.app"
118118
else
119-
APP_BUNDLE="apps/code/out/mac/PostHog Code.app"
119+
APP_BUNDLE="apps/code/out/mac/PostHog.app"
120120
fi
121121
RESOURCES="$APP_BUNDLE/Contents/Resources"
122122
UNPACKED="$RESOURCES/app.asar.unpacked/node_modules"

.github/workflows/code-discord-release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Release PostHog Code to Discord
1+
name: Release PostHog to Discord
22

33
on:
44
release:

.github/workflows/code-release.yml

Lines changed: 162 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Release PostHog Code
1+
name: Release PostHog
22

33
on:
44
push:
@@ -170,9 +170,9 @@ jobs:
170170
MATRIX_ARCH: ${{ matrix.arch }}
171171
run: |
172172
if [[ "$MATRIX_ARCH" == "arm64" ]]; then
173-
APP_BUNDLE="apps/code/out/mac-arm64/PostHog Code.app"
173+
APP_BUNDLE="apps/code/out/mac-arm64/PostHog.app"
174174
else
175-
APP_BUNDLE="apps/code/out/mac/PostHog Code.app"
175+
APP_BUNDLE="apps/code/out/mac/PostHog.app"
176176
fi
177177
RESOURCES="$APP_BUNDLE/Contents/Resources"
178178
UNPACKED="$RESOURCES/app.asar.unpacked/node_modules"
@@ -237,6 +237,25 @@ jobs:
237237
apps/code/out/*-mac.zip \
238238
apps/code/out/*.blockmap
239239
240+
- name: Configure AWS credentials for the update feed
241+
uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1
242+
with:
243+
role-to-assume: ${{ secrets.AWS_DESKTOP_APP_RELEASES_ROLE_ARN }}
244+
aws-region: us-east-1
245+
mask-aws-account-id: true
246+
unset-current-credentials: true
247+
248+
# Binaries carry the version in their filename, so they are immutable.
249+
# Channel files are uploaded last by finalize-release; updaters only see
250+
# this release once those land.
251+
- name: Upload artifacts to the S3 update feed
252+
working-directory: apps/code/out
253+
run: |
254+
for f in *.dmg *-mac.zip *.blockmap; do
255+
aws s3 cp "$f" "s3://posthog-desktop-app-releases-prod-us/stable/$f" \
256+
--cache-control "public, max-age=31536000, immutable"
257+
done
258+
240259
# Hash the same files uploaded above; finalize-release turns these into
241260
# the download tables in the release notes.
242261
- name: Compute artifact checksums
@@ -376,6 +395,35 @@ jobs:
376395
$files = $items | Select-Object -ExpandProperty FullName
377396
gh release upload "v$env:APP_VERSION" --repo PostHog/code --clobber @files
378397
398+
- name: Configure AWS credentials for the update feed
399+
uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1
400+
with:
401+
role-to-assume: ${{ secrets.AWS_DESKTOP_APP_RELEASES_ROLE_ARN }}
402+
aws-region: us-east-1
403+
mask-aws-account-id: true
404+
unset-current-credentials: true
405+
406+
# latest.yml is NOT uploaded here: finalize-release injects release notes
407+
# and publishes it last, which is what flips the S3 feed to this version.
408+
- name: Upload artifacts to the S3 update feed
409+
shell: pwsh
410+
run: |
411+
$out = "apps/code/out"
412+
$items = @()
413+
$items += Get-ChildItem $out -File -Filter "*.exe"
414+
$items += Get-ChildItem $out -File -Filter "*.blockmap"
415+
foreach ($f in $items) {
416+
aws s3 cp $f.FullName "s3://posthog-desktop-app-releases-prod-us/stable/$($f.Name)" --cache-control "public, max-age=31536000, immutable"
417+
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
418+
}
419+
420+
- name: Upload windows manifest artifact
421+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
422+
with:
423+
name: win-manifest
424+
path: apps/code/out/latest.yml
425+
retention-days: 1
426+
379427
# Hash the same files uploaded above (minus latest.yml); finalize-release
380428
# turns these into the download tables in the release notes.
381429
- name: Compute artifact checksums
@@ -522,6 +570,30 @@ jobs:
522570
apps/code/out/*.deb \
523571
apps/code/out/*.rpm
524572
573+
- name: Configure AWS credentials for the update feed
574+
uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1
575+
with:
576+
role-to-assume: ${{ secrets.AWS_DESKTOP_APP_RELEASES_ROLE_ARN }}
577+
aws-region: us-east-1
578+
mask-aws-account-id: true
579+
unset-current-credentials: true
580+
581+
# No Linux auto-updater consumes latest-linux*.yml today (updates are
582+
# macOS and Windows only), so the manifests can ship with the binaries
583+
# instead of waiting for the finalize flip.
584+
- name: Upload artifacts to the S3 update feed
585+
working-directory: apps/code/out
586+
run: |
587+
for f in *.AppImage *.deb *.rpm; do
588+
aws s3 cp "$f" "s3://posthog-desktop-app-releases-prod-us/stable/$f" \
589+
--cache-control "public, max-age=31536000, immutable"
590+
done
591+
for f in latest-linux*.yml; do
592+
[ -e "$f" ] || continue
593+
aws s3 cp "$f" "s3://posthog-desktop-app-releases-prod-us/stable/$f" \
594+
--cache-control "no-cache"
595+
done
596+
525597
# Hash the same files uploaded above; finalize-release turns these into
526598
# the download tables in the release notes.
527599
- name: Compute artifact checksums
@@ -545,6 +617,7 @@ jobs:
545617
runs-on: ubuntu-latest
546618
permissions:
547619
contents: write
620+
id-token: write
548621
steps:
549622
- name: Get app token
550623
id: app-token
@@ -559,12 +632,14 @@ jobs:
559632
TAG_VERSION="${GITHUB_REF#refs/tags/v}"
560633
echo "version=$TAG_VERSION" >> "$GITHUB_OUTPUT"
561634
562-
- name: Checkout merge script
635+
- name: Checkout release scripts
563636
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
564637
with:
565638
sparse-checkout: |
566639
apps/code/scripts/merge-mac-manifests.mjs
567640
apps/code/scripts/generate-release-download-tables.mjs
641+
apps/code/scripts/build-releases-feed.mjs
642+
apps/code/scripts/inject-release-notes.mjs
568643
sparse-checkout-cone-mode: false
569644

570645
- name: Setup Node.js
@@ -618,3 +693,86 @@ jobs:
618693
printf '\n' >> /tmp/release-notes.md
619694
node apps/code/scripts/generate-release-download-tables.mjs "$APP_VERSION" /tmp/checksums >> /tmp/release-notes.md
620695
gh release edit "v$APP_VERSION" --repo PostHog/code --draft=false --notes-file /tmp/release-notes.md
696+
697+
- name: Download windows manifest
698+
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
699+
with:
700+
name: win-manifest
701+
path: /tmp/win-manifest
702+
703+
# Built after the GitHub release is published so the new release (and its
704+
# generated notes) is included; the in-app release notes read this file.
705+
- name: Build releases feed manifest
706+
env:
707+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
708+
run: node apps/code/scripts/build-releases-feed.mjs /tmp/releases.json
709+
710+
# The generic provider fetches nothing from GitHub, so the channel files
711+
# must carry the notes for electron-updater's UpdateInfo.releaseNotes.
712+
- name: Inject release notes into channel files
713+
run: |
714+
node apps/code/scripts/inject-release-notes.mjs /tmp/release-notes.md \
715+
/tmp/latest-mac.yml /tmp/win-manifest/latest.yml
716+
717+
- name: Configure AWS credentials for the update feed
718+
uses: aws-actions/configure-aws-credentials@254c19bd240aabef8777f48595e9d2d7b972184b # v6.2.1
719+
with:
720+
role-to-assume: ${{ secrets.AWS_DESKTOP_APP_RELEASES_ROLE_ARN }}
721+
aws-region: us-east-1
722+
mask-aws-account-id: true
723+
unset-current-credentials: true
724+
725+
# The channel-file upload is the S3 publish flip: updaters only see the
726+
# new version once these land, after every platform's binaries are up.
727+
# Stage all files first, then flip with server-side copies, so a failed
728+
# runner upload can never leave the feed advertising a mixed release
729+
# (e.g. macOS on the new version while Windows still serves the old one).
730+
# Copies preserve the staged objects' cache-control metadata.
731+
- name: Publish channel files to the S3 update feed
732+
env:
733+
APP_VERSION: ${{ steps.version.outputs.version }}
734+
run: |
735+
FEED="s3://posthog-desktop-app-releases-prod-us/stable"
736+
STAGING="$FEED/.staging/v$APP_VERSION"
737+
738+
aws s3 cp /tmp/latest-mac.yml "$STAGING/latest-mac.yml" --cache-control "no-cache"
739+
aws s3 cp /tmp/win-manifest/latest.yml "$STAGING/latest.yml" --cache-control "no-cache"
740+
aws s3 cp /tmp/releases.json "$STAGING/releases.json" --cache-control "no-cache"
741+
742+
aws s3 cp "$STAGING/latest-mac.yml" "$FEED/latest-mac.yml"
743+
aws s3 cp "$STAGING/latest.yml" "$FEED/latest.yml"
744+
aws s3 cp "$STAGING/releases.json" "$FEED/releases.json"
745+
746+
aws s3 rm --recursive "$STAGING/" || echo "staging cleanup failed; harmless"
747+
748+
# The little markdown table in the run summary: public CloudFront URLs for
749+
# everything this release published to the feed.
750+
- name: Write release summary
751+
env:
752+
APP_VERSION: ${{ steps.version.outputs.version }}
753+
run: |
754+
BASE="https://desktop-releases.posthog.com/stable"
755+
V="$APP_VERSION"
756+
{
757+
echo "## v$V on the update feed"
758+
echo ""
759+
echo "| Artifact | URL |"
760+
echo "| --- | --- |"
761+
for f in \
762+
"PostHog-Code-$V-arm64-mac.dmg" \
763+
"PostHog-Code-$V-arm64-mac.zip" \
764+
"PostHog-Code-$V-x64-mac.dmg" \
765+
"PostHog-Code-$V-x64-mac.zip" \
766+
"PostHog-Code-$V-x64-win.exe" \
767+
"PostHog-Code-$V-arm64-linux.AppImage" \
768+
"PostHog-Code-$V-arm64-linux.deb" \
769+
"PostHog-Code-$V-arm64-linux.rpm" \
770+
"PostHog-Code-$V-x64-linux.AppImage" \
771+
"PostHog-Code-$V-x64-linux.deb" \
772+
"PostHog-Code-$V-x64-linux.rpm" \
773+
"latest-mac.yml" \
774+
"latest.yml" \
775+
"releases.json"; do
776+
echo "| \`$f\` | $BASE/$f |"
777+
done
778+
} >> "$GITHUB_STEP_SUMMARY"

.github/workflows/code-storybook.yml

Lines changed: 6 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,13 @@ jobs:
115115
restore-keys: |
116116
playwright-chromium-${{ runner.os }}-
117117
118+
- name: Restore turbo cache
119+
uses: ./.github/actions/restore-turbo-cache
120+
118121
- name: Install dependencies
119122
run: pnpm install --frozen-lockfile
123+
env:
124+
SKIP_ELECTRON_REBUILD: "1"
120125

121126
- name: Install Playwright Chromium
122127
if: steps.playwright-cache.outputs.cache-hit != 'true'
@@ -130,38 +135,7 @@ jobs:
130135
run: pnpm exec playwright install-deps chromium
131136

132137
- name: Build workspace packages
133-
# Bare `wait` returns the exit status of only the last job passed to
134-
# it, silently swallowing failures from the others. `wait_all` waits
135-
# on each PID individually and checks its own status so any failed
136-
# build fails the step.
137-
run: |
138-
wait_all() {
139-
status=0
140-
for pid in "$@"; do
141-
wait "$pid" || status=$?
142-
done
143-
[ "$status" -eq 0 ]
144-
}
145-
146-
pnpm --filter @posthog/electron-trpc build &
147-
pid1=$!
148-
(pnpm --filter @posthog/shared build && pnpm --filter @posthog/platform build) &
149-
pid2=$!
150-
wait_all "$pid1" "$pid2"
151-
152-
# @posthog/agent imports the dist of @posthog/git and
153-
# @posthog/harness, so both must finish before the last group starts.
154-
pnpm --filter @posthog/git build &
155-
pid3=$!
156-
pnpm --filter @posthog/harness build &
157-
pid4=$!
158-
wait_all "$pid3" "$pid4"
159-
160-
pnpm --filter @posthog/enricher build &
161-
pid5=$!
162-
pnpm --filter @posthog/agent build &
163-
pid6=$!
164-
wait_all "$pid5" "$pid6"
138+
run: pnpm run build:deps
165139

166140
- name: Build Storybook
167141
working-directory: apps/code

0 commit comments

Comments
 (0)