Skip to content

Commit 86af103

Browse files
authored
Merge pull request #4952 from RSSNext/release/mobile/0.4.1
release(mobile): Release v0.4.1
2 parents a46b8be + cae21c1 commit 86af103

277 files changed

Lines changed: 17908 additions & 3603 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.

.agents/skills/mobile-self-test/SKILL.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ This skill extends `../mobile-e2e/SKILL.md`. Read that skill first for the basel
1818
- iOS register flow: `apps/mobile/e2e/flows/ios/register.yaml`
1919
- Android register flow: `apps/mobile/e2e/flows/android/register.yaml`
2020
- Shared auth flows: `apps/mobile/e2e/flows/shared/*.yaml`
21+
- iOS interaction skill: `/Users/diygod/.agents/skills/axe/SKILL.md`
2122
- Expo config: `apps/mobile/app.config.ts`
2223
- Build profiles: `apps/mobile/eas.json`
2324
- Mobile artifacts: `apps/mobile/e2e/artifacts/`
@@ -185,6 +186,10 @@ xcrun simctl install "$IOS_UDID" <PATH_TO_Folo.app>
185186
xcrun simctl launch "$IOS_UDID" is.follow
186187
```
187188

189+
### iOS interaction after launch
190+
191+
After the app is running on the dedicated iOS simulator, use the `$axe` skill for simulator interaction during visual validation. Use `$axe` as the default interaction layer for iOS screenshot-driven checks.
192+
188193
## Android workflow
189194

190195
Reuse the Java and Android SDK setup from `../mobile-e2e/SKILL.md`.
@@ -364,7 +369,7 @@ For auth-related work:
364369

365370
## Screenshot-driven visual testing
366371

367-
Once the app is in the right state, drive the rest of the validation with the visual toolchain available in the current environment. Screenshots are the source of truth for acceptance.
372+
Once the app is in the right state, drive the rest of the validation visually. On iOS, use the `$axe` skill as the default interaction tool for this phase. On Android, use the interaction tooling available in the current environment. Screenshots are the source of truth for acceptance.
368373

369374
Create a timestamped artifact folder first:
370375

@@ -430,4 +435,5 @@ If the client supports local image rendering, attach the key screenshots as imag
430435

431436
- If doctor, typecheck, build, install, or server startup fails, stop and report the exact failing command.
432437
- If `local` mode cannot reach the local server, do not silently fall back to `prod`.
433-
- If the visual flow cannot be completed because the environment lacks the required interaction tooling, report that limitation clearly and still return the screenshots you captured.
438+
- If the iOS visual flow cannot be completed because `$axe` is unavailable or unusable, report that limitation clearly and still return the screenshots you captured.
439+
- If the Android visual flow cannot be completed because the environment lacks suitable interaction tooling, report that limitation clearly and still return the screenshots you captured.

.github/workflows/build-desktop.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ env:
2929
VITE_WEB_URL: ${{ vars.VITE_WEB_URL }}
3030
VITE_API_URL: ${{ vars.VITE_API_URL }}
3131
VITE_SENTRY_DSN: ${{ vars.VITE_SENTRY_DSN }}
32-
VITE_OPENPANEL_CLIENT_ID: ${{ vars.VITE_OPENPANEL_CLIENT_ID }}
33-
VITE_OPENPANEL_API_URL: ${{ vars.VITE_OPENPANEL_API_URL }}
3432
VITE_FIREBASE_CONFIG: ${{ vars.VITE_FIREBASE_CONFIG }}
3533
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
3634
NODE_OPTIONS: --max-old-space-size=8192
@@ -153,7 +151,7 @@ jobs:
153151
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
154152
OSX_SIGN_KEYCHAIN_PATH: ${{ runner.temp }}/app-signing.keychain-db
155153
OSX_SIGN_IDENTITY: ${{ secrets.OSX_SIGN_IDENTITY }}
156-
uses: nick-fields/retry@v3
154+
uses: nick-fields/retry@v4
157155
with:
158156
max_attempts: 3
159157
timeout_minutes: 10
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
name: "\u2601\ufe0f Deploy Desktop to Cloudflare"
2+
3+
on:
4+
push:
5+
branches: [main, dev]
6+
7+
concurrency:
8+
group: ${{ github.workflow }}-${{ github.ref }}
9+
cancel-in-progress: true
10+
11+
jobs:
12+
deploy:
13+
name: Build & Deploy Desktop Web
14+
runs-on: ubuntu-latest
15+
env:
16+
VITE_SENTRY_DSN: ${{ vars.VITE_SENTRY_DSN }}
17+
VITE_FIREBASE_CONFIG: ${{ vars.VITE_FIREBASE_CONFIG }}
18+
steps:
19+
- name: Checkout code
20+
uses: actions/checkout@v6
21+
with:
22+
lfs: true
23+
24+
- name: Checkout LFS objects
25+
run: git lfs checkout
26+
27+
- name: Cache turbo build setup
28+
uses: actions/cache@v5
29+
with:
30+
path: .turbo
31+
key: ${{ runner.os }}-turbo-${{ github.sha }}
32+
restore-keys: |
33+
${{ runner.os }}-turbo-
34+
35+
- uses: pnpm/action-setup@v4
36+
37+
- name: Use Node.js LTS
38+
uses: actions/setup-node@v6
39+
with:
40+
node-version: lts/*
41+
cache: "pnpm"
42+
43+
- name: Install dependencies
44+
run: pnpm install
45+
46+
- name: Build desktop web (SPA)
47+
working-directory: apps/desktop
48+
env:
49+
VITE_WEB_URL: ${{ github.ref == 'refs/heads/dev' && 'https://dev.folo.is' || 'https://app.folo.is' }}
50+
VITE_API_URL: ${{ github.ref == 'refs/heads/dev' && 'https://api.dev.folo.is' || 'https://api.folo.is' }}
51+
run: pnpm run build:web
52+
53+
- name: Deploy desktop web to Cloudflare (dev)
54+
if: github.ref == 'refs/heads/dev'
55+
uses: cloudflare/wrangler-action@v3
56+
with:
57+
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
58+
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
59+
workingDirectory: apps/desktop
60+
command: deploy --env dev
61+
62+
- name: Deploy desktop web to Cloudflare (prod)
63+
if: github.ref == 'refs/heads/main'
64+
uses: cloudflare/wrangler-action@v3
65+
with:
66+
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
67+
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
68+
workingDirectory: apps/desktop
69+
command: 'deploy --env=""'

.github/workflows/deploy-cloudflare.yml renamed to .github/workflows/deploy-cloudflare-landing.yml

Lines changed: 33 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
1+
name: "\u2601\ufe0f Deploy Landing to Cloudflare"
2+
13
on:
24
push:
35
branches: [main, dev]
6+
workflow_dispatch:
7+
inputs:
8+
confirm_production_deploy:
9+
description: Deploy the selected branch to production (folo.is)
10+
required: true
11+
default: false
12+
type: boolean
413

5-
name: ☁️ Deploy to Cloudflare Workers
614
concurrency:
7-
group: ${{ github.workflow }}-${{ github.ref }}
15+
group: ${{ github.workflow }}-${{ github.event_name == 'workflow_dispatch' && format('manual-prod-{0}', github.ref) || github.ref }}
816
cancel-in-progress: true
17+
918
jobs:
1019
deploy:
11-
name: Build & Deploy
20+
name: Build & Deploy Landing Worker
1221
runs-on: ubuntu-latest
13-
strategy:
14-
matrix:
15-
node-version: [lts/*]
1622
steps:
1723
- name: Checkout code
1824
uses: actions/checkout@v6
@@ -32,57 +38,49 @@ jobs:
3238
3339
- uses: pnpm/action-setup@v4
3440

35-
- name: Use Node.js ${{ matrix.node-version }}
41+
- name: Use Node.js LTS
3642
uses: actions/setup-node@v6
3743
with:
38-
node-version: ${{ matrix.node-version }}
44+
node-version: lts/*
3945
cache: "pnpm"
4046

4147
- name: Install dependencies
4248
run: pnpm install
4349

44-
- name: Build desktop web (SPA)
45-
run: pnpm exec turbo run Folo#build:web
50+
- name: Resolve deployment target
51+
id: target
52+
run: |
53+
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
54+
if [[ "${{ inputs.confirm_production_deploy }}" != "true" ]]; then
55+
echo "Manual production deploy was not confirmed." >&2
56+
exit 1
57+
fi
4658
47-
- name: Build SSR Worker
48-
working-directory: apps/ssr
49-
run: pnpm run build:worker
59+
echo "environment=prod" >> "$GITHUB_OUTPUT"
60+
exit 0
61+
fi
5062
51-
- name: Copy WASM file
52-
run: cp node_modules/@resvg/resvg-wasm/index_bg.wasm apps/ssr/dist/worker/resvg.wasm
63+
if [[ "${{ github.ref }}" == "refs/heads/dev" ]]; then
64+
echo "environment=dev" >> "$GITHUB_OUTPUT"
65+
exit 0
66+
fi
67+
68+
echo "environment=prod" >> "$GITHUB_OUTPUT"
5369
5470
- name: Build Landing Worker
5571
run: pnpm exec turbo run @follow/landing#cf:build
5672

57-
- name: Deploy to Cloudflare (dev)
58-
if: github.ref == 'refs/heads/dev'
59-
uses: cloudflare/wrangler-action@v3
60-
with:
61-
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
62-
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
63-
workingDirectory: apps/ssr
64-
command: deploy --env dev
65-
6673
- name: Deploy Landing to Cloudflare (dev)
67-
if: github.ref == 'refs/heads/dev'
74+
if: steps.target.outputs.environment == 'dev'
6875
uses: cloudflare/wrangler-action@v3
6976
with:
7077
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
7178
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
7279
workingDirectory: apps/landing
7380
command: deploy --env dev --name landing-next-dev --routes landing.dev.folo.is/*
7481

75-
- name: Deploy to Cloudflare (prod)
76-
if: github.ref == 'refs/heads/main'
77-
uses: cloudflare/wrangler-action@v3
78-
with:
79-
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
80-
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
81-
workingDirectory: apps/ssr
82-
command: deploy
83-
8482
- name: Deploy Landing to Cloudflare (prod)
85-
if: github.ref == 'refs/heads/main'
83+
if: steps.target.outputs.environment == 'prod'
8684
uses: cloudflare/wrangler-action@v3
8785
with:
8886
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
name: "\u2601\ufe0f Deploy SSR to Cloudflare"
2+
3+
on:
4+
push:
5+
branches: [main, dev]
6+
workflow_dispatch:
7+
inputs:
8+
confirm_production_deploy:
9+
description: Deploy the selected branch to production (app.folo.is)
10+
required: true
11+
default: false
12+
type: boolean
13+
14+
concurrency:
15+
group: ${{ github.workflow }}-${{ github.event_name == 'workflow_dispatch' && format('manual-prod-{0}', github.ref) || github.ref }}
16+
cancel-in-progress: true
17+
18+
jobs:
19+
deploy:
20+
name: Build & Deploy SSR Worker
21+
runs-on: ubuntu-latest
22+
env:
23+
VITE_SENTRY_DSN: ${{ vars.VITE_SENTRY_DSN }}
24+
VITE_FIREBASE_CONFIG: ${{ vars.VITE_FIREBASE_CONFIG }}
25+
steps:
26+
- name: Checkout code
27+
uses: actions/checkout@v6
28+
with:
29+
lfs: true
30+
31+
- name: Checkout LFS objects
32+
run: git lfs checkout
33+
34+
- name: Cache turbo build setup
35+
uses: actions/cache@v5
36+
with:
37+
path: .turbo
38+
key: ${{ runner.os }}-turbo-${{ github.sha }}
39+
restore-keys: |
40+
${{ runner.os }}-turbo-
41+
42+
- uses: pnpm/action-setup@v4
43+
44+
- name: Use Node.js LTS
45+
uses: actions/setup-node@v6
46+
with:
47+
node-version: lts/*
48+
cache: "pnpm"
49+
50+
- name: Install dependencies
51+
run: pnpm install
52+
53+
- name: Resolve deployment target
54+
id: target
55+
run: |
56+
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
57+
if [[ "${{ inputs.confirm_production_deploy }}" != "true" ]]; then
58+
echo "Manual production deploy was not confirmed." >&2
59+
exit 1
60+
fi
61+
62+
echo "environment=prod" >> "$GITHUB_OUTPUT"
63+
echo "vite_web_url=https://app.folo.is" >> "$GITHUB_OUTPUT"
64+
echo "vite_api_url=https://api.folo.is" >> "$GITHUB_OUTPUT"
65+
exit 0
66+
fi
67+
68+
if [[ "${{ github.ref }}" == "refs/heads/dev" ]]; then
69+
echo "environment=dev" >> "$GITHUB_OUTPUT"
70+
echo "vite_web_url=https://dev.folo.is" >> "$GITHUB_OUTPUT"
71+
echo "vite_api_url=https://api.dev.folo.is" >> "$GITHUB_OUTPUT"
72+
exit 0
73+
fi
74+
75+
echo "environment=prod" >> "$GITHUB_OUTPUT"
76+
echo "vite_web_url=https://app.folo.is" >> "$GITHUB_OUTPUT"
77+
echo "vite_api_url=https://api.folo.is" >> "$GITHUB_OUTPUT"
78+
79+
- name: Build desktop web (SSR assets)
80+
working-directory: apps/desktop
81+
env:
82+
VITE_WEB_URL: ${{ steps.target.outputs.vite_web_url }}
83+
VITE_API_URL: ${{ steps.target.outputs.vite_api_url }}
84+
run: pnpm run build:web
85+
86+
- name: Build SSR Worker
87+
working-directory: apps/ssr
88+
run: pnpm run build:worker
89+
90+
- name: Copy WASM file
91+
run: cp node_modules/@resvg/resvg-wasm/index_bg.wasm apps/ssr/dist/worker/resvg.wasm
92+
93+
- name: Deploy SSR Worker to Cloudflare (dev)
94+
if: steps.target.outputs.environment == 'dev'
95+
uses: cloudflare/wrangler-action@v3
96+
with:
97+
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
98+
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
99+
workingDirectory: apps/ssr
100+
command: deploy --env dev
101+
102+
- name: Deploy SSR Worker to Cloudflare (prod)
103+
if: steps.target.outputs.environment == 'prod'
104+
uses: cloudflare/wrangler-action@v3
105+
with:
106+
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
107+
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
108+
workingDirectory: apps/ssr
109+
command: 'deploy --env=""'

.prettierrc.mjs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/** @type {import("prettier").Config & import("prettier-plugin-tailwindcss").PluginOptions} */
12
export default {
23
semi: false,
34
singleQuote: false,
@@ -6,4 +7,25 @@ export default {
67
trailingComma: "all",
78
objectWrap: "preserve",
89
plugins: ["prettier-plugin-tailwindcss"],
10+
tailwindConfig: "./apps/desktop/tailwind.config.ts",
11+
overrides: [
12+
{
13+
files: "apps/mobile/**/*.{css,js,jsx,ts,tsx}",
14+
options: {
15+
tailwindConfig: "./apps/mobile/tailwind.config.ts",
16+
},
17+
},
18+
{
19+
files: "apps/mobile/web-app/html-renderer/**/*.{css,js,jsx,ts,tsx}",
20+
options: {
21+
tailwindConfig: "./apps/mobile/web-app/html-renderer/tailwind.config.ts",
22+
},
23+
},
24+
{
25+
files: "apps/ssr/**/*.{css,html,js,jsx,ts,tsx}",
26+
options: {
27+
tailwindConfig: "./apps/ssr/tailwind.config.ts",
28+
},
29+
},
30+
],
931
}

0 commit comments

Comments
 (0)