ios-app-review-plugin 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +42 -0
- package/.github/actions/ios-review/action.yml +106 -0
- package/.github/workflows/ci.yml +103 -0
- package/.github/workflows/publish.yml +57 -0
- package/CHANGELOG.md +66 -0
- package/CONTRIBUTING.md +175 -0
- package/LICENSE +21 -0
- package/README.md +205 -0
- package/bitrise/step.sh +128 -0
- package/bitrise/step.yml +101 -0
- package/dist/analyzer.d.ts.map +1 -0
- package/dist/analyzers/asc-iap.d.ts.map +1 -0
- package/dist/analyzers/asc-metadata.d.ts.map +1 -0
- package/dist/analyzers/asc-screenshots.d.ts.map +1 -0
- package/dist/analyzers/asc-version.d.ts.map +1 -0
- package/dist/analyzers/code-scanner.d.ts.map +1 -0
- package/dist/analyzers/deprecated-api.d.ts.map +1 -0
- package/dist/analyzers/entitlements.d.ts.map +1 -0
- package/dist/analyzers/index.d.ts.map +1 -0
- package/dist/analyzers/info-plist.d.ts.map +1 -0
- package/dist/analyzers/privacy.d.ts.map +1 -0
- package/dist/analyzers/private-api.d.ts.map +1 -0
- package/dist/analyzers/security.d.ts.map +1 -0
- package/dist/analyzers/ui-ux.d.ts.map +1 -0
- package/dist/asc/auth.d.ts.map +1 -0
- package/dist/asc/client.d.ts.map +1 -0
- package/dist/asc/endpoints/apps.d.ts.map +1 -0
- package/dist/asc/endpoints/iap.d.ts.map +1 -0
- package/dist/asc/endpoints/screenshots.d.ts.map +1 -0
- package/dist/asc/endpoints/versions.d.ts.map +1 -0
- package/dist/asc/errors.d.ts.map +1 -0
- package/dist/asc/index.d.ts.map +1 -0
- package/dist/asc/types.d.ts.map +1 -0
- package/dist/badge/generator.d.ts.map +1 -0
- package/dist/badge/index.d.ts.map +1 -0
- package/dist/badge/types.d.ts.map +1 -0
- package/dist/cache/file-cache.d.ts.map +1 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/types.d.ts.map +1 -0
- package/dist/cli/commands/help.d.ts.map +1 -0
- package/dist/cli/commands/scan.d.ts.map +1 -0
- package/dist/cli/commands/version.d.ts.map +1 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/git/diff.d.ts.map +1 -0
- package/dist/git/index.d.ts.map +1 -0
- package/dist/git/types.d.ts.map +1 -0
- package/dist/guidelines/database.d.ts.map +1 -0
- package/dist/guidelines/index.d.ts.map +1 -0
- package/dist/guidelines/matcher.d.ts.map +1 -0
- package/dist/guidelines/types.d.ts.map +1 -0
- package/dist/history/comparator.d.ts.map +1 -0
- package/dist/history/index.d.ts.map +1 -0
- package/dist/history/store.d.ts.map +1 -0
- package/dist/history/types.d.ts.map +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +994 -0
- package/dist/parsers/index.d.ts.map +1 -0
- package/dist/parsers/plist.d.ts.map +1 -0
- package/dist/parsers/xcodeproj.d.ts.map +1 -0
- package/dist/progress/index.d.ts.map +1 -0
- package/dist/progress/reporter.d.ts.map +1 -0
- package/dist/progress/types.d.ts.map +1 -0
- package/dist/reports/html.d.ts.map +1 -0
- package/dist/reports/index.d.ts.map +1 -0
- package/dist/reports/json.d.ts.map +1 -0
- package/dist/reports/markdown.d.ts.map +1 -0
- package/dist/reports/types.d.ts.map +1 -0
- package/dist/rules/engine.d.ts.map +1 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/loader.d.ts.map +1 -0
- package/dist/rules/types.d.ts.map +1 -0
- package/dist/types/index.d.ts.map +1 -0
- package/docs/ANALYZERS.md +237 -0
- package/docs/API.md +308 -0
- package/docs/BADGES.md +130 -0
- package/docs/CI_CD.md +283 -0
- package/docs/CLI.md +140 -0
- package/docs/REPORTS.md +212 -0
- package/docs/ROADMAP.md +267 -0
- package/docs/RULES.md +182 -0
- package/docs/SECURITY.md +89 -0
- package/docs/TROUBLESHOOTING.md +227 -0
- package/docs/tutorials/ASC_SETUP.md +188 -0
- package/docs/tutorials/CI_INTEGRATION.md +292 -0
- package/docs/tutorials/CUSTOM_RULES.md +291 -0
- package/docs/tutorials/GETTING_STARTED.md +226 -0
- package/docs/video-scripts/01-introduction.md +106 -0
- package/docs/video-scripts/02-cli-usage.md +120 -0
- package/docs/video-scripts/03-ci-integration.md +198 -0
- package/eslint.config.js +33 -0
- package/examples/.ios-review-rules.json +82 -0
- package/examples/bitrise-workflow.yml +129 -0
- package/examples/fastlane-lane.rb +71 -0
- package/examples/github-action.yml +147 -0
- package/fastlane/Fastfile.example +114 -0
- package/fastlane/README.md +99 -0
- package/jest.config.js +36 -0
- package/package.json +65 -0
- package/scripts/benchmark.ts +112 -0
- package/scripts/debug-parser.ts +37 -0
- package/scripts/debug-pbxproj.ts +36 -0
- package/scripts/debug-specific.ts +47 -0
- package/scripts/test-analyze.ts +67 -0
- package/scripts/xcode-cloud-review.sh +167 -0
- package/src/analyzer.ts +227 -0
- package/src/analyzers/asc-iap.ts +300 -0
- package/src/analyzers/asc-metadata.ts +326 -0
- package/src/analyzers/asc-screenshots.ts +310 -0
- package/src/analyzers/asc-version.ts +368 -0
- package/src/analyzers/code-scanner.ts +408 -0
- package/src/analyzers/deprecated-api.ts +390 -0
- package/src/analyzers/entitlements.ts +345 -0
- package/src/analyzers/index.ts +12 -0
- package/src/analyzers/info-plist.ts +409 -0
- package/src/analyzers/privacy.ts +376 -0
- package/src/analyzers/private-api.ts +377 -0
- package/src/analyzers/security.ts +327 -0
- package/src/analyzers/ui-ux.ts +509 -0
- package/src/asc/auth.ts +204 -0
- package/src/asc/client.ts +258 -0
- package/src/asc/endpoints/apps.ts +115 -0
- package/src/asc/endpoints/iap.ts +171 -0
- package/src/asc/endpoints/screenshots.ts +164 -0
- package/src/asc/endpoints/versions.ts +174 -0
- package/src/asc/errors.ts +109 -0
- package/src/asc/index.ts +108 -0
- package/src/asc/types.ts +369 -0
- package/src/badge/generator.ts +48 -0
- package/src/badge/index.ts +2 -0
- package/src/badge/types.ts +5 -0
- package/src/cache/file-cache.ts +75 -0
- package/src/cache/index.ts +2 -0
- package/src/cache/types.ts +10 -0
- package/src/cli/commands/help.ts +41 -0
- package/src/cli/commands/scan.ts +44 -0
- package/src/cli/commands/version.ts +12 -0
- package/src/cli/index.ts +92 -0
- package/src/cli/types.ts +17 -0
- package/src/git/diff.ts +21 -0
- package/src/git/index.ts +2 -0
- package/src/git/types.ts +5 -0
- package/src/guidelines/database.ts +344 -0
- package/src/guidelines/index.ts +4 -0
- package/src/guidelines/matcher.ts +84 -0
- package/src/guidelines/types.ts +28 -0
- package/src/history/comparator.ts +114 -0
- package/src/history/index.ts +3 -0
- package/src/history/store.ts +135 -0
- package/src/history/types.ts +40 -0
- package/src/index.ts +1113 -0
- package/src/parsers/index.ts +3 -0
- package/src/parsers/plist.ts +253 -0
- package/src/parsers/xcodeproj.ts +265 -0
- package/src/progress/index.ts +2 -0
- package/src/progress/reporter.ts +65 -0
- package/src/progress/types.ts +9 -0
- package/src/reports/html.ts +322 -0
- package/src/reports/index.ts +20 -0
- package/src/reports/json.ts +92 -0
- package/src/reports/markdown.ts +187 -0
- package/src/reports/types.ts +26 -0
- package/src/rules/engine.ts +121 -0
- package/src/rules/index.ts +3 -0
- package/src/rules/loader.ts +83 -0
- package/src/rules/types.ts +25 -0
- package/src/types/index.ts +247 -0
- package/tests/analyzer.test.ts +142 -0
- package/tests/analyzers/asc-iap.test.ts +228 -0
- package/tests/analyzers/asc-metadata.test.ts +210 -0
- package/tests/analyzers/asc-screenshots.test.ts +135 -0
- package/tests/analyzers/asc-version.test.ts +259 -0
- package/tests/analyzers/code-scanner.test.ts +745 -0
- package/tests/analyzers/deprecated-api.test.ts +286 -0
- package/tests/analyzers/entitlements.test.ts +411 -0
- package/tests/analyzers/info-plist.test.ts +148 -0
- package/tests/analyzers/privacy.test.ts +623 -0
- package/tests/analyzers/private-api.test.ts +255 -0
- package/tests/analyzers/security.test.ts +300 -0
- package/tests/analyzers/ui-ux.test.ts +357 -0
- package/tests/asc/auth.test.ts +189 -0
- package/tests/asc/client.test.ts +207 -0
- package/tests/asc/endpoints.test.ts +1359 -0
- package/tests/badge/generator.test.ts +73 -0
- package/tests/cache/file-cache.test.ts +124 -0
- package/tests/cli/cli-index.test.ts +510 -0
- package/tests/cli/commands.test.ts +67 -0
- package/tests/cli/scan.test.ts +152 -0
- package/tests/git/diff.test.ts +69 -0
- package/tests/guidelines/matcher.test.ts +209 -0
- package/tests/history/comparator.test.ts +272 -0
- package/tests/history/store.test.ts +200 -0
- package/tests/integration/cli.test.ts +95 -0
- package/tests/integration/e2e.test.ts +130 -0
- package/tests/parsers/plist.test.ts +240 -0
- package/tests/parsers/xcodeproj.test.ts +289 -0
- package/tests/progress/reporter.test.ts +117 -0
- package/tests/reports/html.test.ts +176 -0
- package/tests/reports/json.test.ts +235 -0
- package/tests/reports/markdown.test.ts +196 -0
- package/tests/rules/engine.test.ts +229 -0
- package/tests/rules/loader.test.ts +187 -0
- package/tests/setup.ts +15 -0
- package/tsconfig.json +27 -0
- package/tsconfig.test.json +9 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# Getting Started
|
|
2
|
+
|
|
3
|
+
This tutorial walks through installing the plugin, running your first scan, understanding the results, and fixing common issues.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- Node.js >= 18
|
|
8
|
+
- An iOS project (`.xcodeproj` or `.xcworkspace`)
|
|
9
|
+
- (Optional) App Store Connect API key for ASC validation
|
|
10
|
+
|
|
11
|
+
## Step 1: Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
git clone https://github.com/ahmetsina/ios-app-review-plugin.git
|
|
15
|
+
cd ios-app-review-plugin
|
|
16
|
+
npm install
|
|
17
|
+
npm run build
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
To use the CLI globally:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm link
|
|
24
|
+
# or
|
|
25
|
+
npm install -g .
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Verify:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
ios-app-review version
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Step 2: Run Your First Scan
|
|
35
|
+
|
|
36
|
+
Point the tool at your Xcode project:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
ios-app-review scan /path/to/MyApp.xcodeproj
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
This runs all 8 core analyzers and prints a Markdown report to stdout. A typical first run takes 1-5 seconds depending on project size.
|
|
43
|
+
|
|
44
|
+
### What Happens During a Scan
|
|
45
|
+
|
|
46
|
+
1. The Xcode project file (`.pbxproj`) is parsed to discover targets, source files, Info.plist paths, and entitlements paths.
|
|
47
|
+
2. Each analyzer runs in parallel against the relevant files.
|
|
48
|
+
3. Issues are collected and enriched with guideline cross-references.
|
|
49
|
+
4. A readiness score (0-100) is calculated.
|
|
50
|
+
5. The formatted report is printed.
|
|
51
|
+
|
|
52
|
+
## Step 3: Understand the Results
|
|
53
|
+
|
|
54
|
+
The report has these sections:
|
|
55
|
+
|
|
56
|
+
### Review Readiness Score
|
|
57
|
+
|
|
58
|
+
A number from 0 to 100. Higher is better. The score is calculated based on the number and severity of issues found, weighted by the corresponding App Store Review Guideline importance.
|
|
59
|
+
|
|
60
|
+
- **80-100:** Ready for submission. Minor tweaks may help.
|
|
61
|
+
- **50-79:** Several issues to address. Likely rejection if errors remain.
|
|
62
|
+
- **0-49:** Significant problems. Address all errors before submitting.
|
|
63
|
+
|
|
64
|
+
### Summary Table
|
|
65
|
+
|
|
66
|
+
Quick counts of errors, warnings, and info items plus total scan duration.
|
|
67
|
+
|
|
68
|
+
### Priority Remediation
|
|
69
|
+
|
|
70
|
+
Error-severity issues sorted by guideline severity weight. Fix these first -- they are the most likely rejection causes.
|
|
71
|
+
|
|
72
|
+
### Issues by Category
|
|
73
|
+
|
|
74
|
+
All issues grouped by category (Info.plist, Privacy, Code Quality, Security, etc.). Each issue includes:
|
|
75
|
+
|
|
76
|
+
- **Severity badge** -- `[ERROR]` must be fixed, `[WARN]` should be fixed, `[INFO]` is advisory
|
|
77
|
+
- **Title** -- Brief description
|
|
78
|
+
- **Description** -- Details and the code/pattern that triggered it
|
|
79
|
+
- **Location** -- File path and line number
|
|
80
|
+
- **Guideline** -- Link to the relevant Apple guideline
|
|
81
|
+
- **Suggestion** -- How to fix it
|
|
82
|
+
|
|
83
|
+
## Step 4: Fix Common Issues
|
|
84
|
+
|
|
85
|
+
### Errors (Must Fix)
|
|
86
|
+
|
|
87
|
+
**Missing required Info.plist keys:**
|
|
88
|
+
|
|
89
|
+
```xml
|
|
90
|
+
<!-- Add to Info.plist -->
|
|
91
|
+
<key>CFBundleExecutable</key>
|
|
92
|
+
<string>$(EXECUTABLE_NAME)</string>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**Hardcoded API keys:**
|
|
96
|
+
|
|
97
|
+
```swift
|
|
98
|
+
// BAD
|
|
99
|
+
let apiKey = "sk-1234567890abcdef"
|
|
100
|
+
|
|
101
|
+
// GOOD
|
|
102
|
+
let apiKey = ProcessInfo.processInfo.environment["API_KEY"] ?? ""
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**UIWebView usage:**
|
|
106
|
+
|
|
107
|
+
Replace all `UIWebView` instances with `WKWebView`:
|
|
108
|
+
|
|
109
|
+
```swift
|
|
110
|
+
// BAD
|
|
111
|
+
let webView = UIWebView()
|
|
112
|
+
|
|
113
|
+
// GOOD
|
|
114
|
+
import WebKit
|
|
115
|
+
let webView = WKWebView()
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**Missing privacy manifest:**
|
|
119
|
+
|
|
120
|
+
Create `PrivacyInfo.xcprivacy` in your project and declare Required Reason APIs:
|
|
121
|
+
|
|
122
|
+
```xml
|
|
123
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
124
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "...">
|
|
125
|
+
<plist version="1.0">
|
|
126
|
+
<dict>
|
|
127
|
+
<key>NSPrivacyAccessedAPITypes</key>
|
|
128
|
+
<array>
|
|
129
|
+
<dict>
|
|
130
|
+
<key>NSPrivacyAccessedAPIType</key>
|
|
131
|
+
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
|
132
|
+
<key>NSPrivacyAccessedAPITypeReasons</key>
|
|
133
|
+
<array>
|
|
134
|
+
<string>CA92.1</string>
|
|
135
|
+
</array>
|
|
136
|
+
</dict>
|
|
137
|
+
</array>
|
|
138
|
+
</dict>
|
|
139
|
+
</plist>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Warnings (Should Fix)
|
|
143
|
+
|
|
144
|
+
**ATS allows arbitrary loads:**
|
|
145
|
+
|
|
146
|
+
Remove the global bypass and use exception domains for specific servers:
|
|
147
|
+
|
|
148
|
+
```xml
|
|
149
|
+
<key>NSAppTransportSecurity</key>
|
|
150
|
+
<dict>
|
|
151
|
+
<key>NSExceptionDomains</key>
|
|
152
|
+
<dict>
|
|
153
|
+
<key>legacy-api.example.com</key>
|
|
154
|
+
<dict>
|
|
155
|
+
<key>NSExceptionAllowsInsecureHTTPLoads</key>
|
|
156
|
+
<true/>
|
|
157
|
+
</dict>
|
|
158
|
+
</dict>
|
|
159
|
+
</dict>
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**Hardcoded IPv4 addresses:**
|
|
163
|
+
|
|
164
|
+
```swift
|
|
165
|
+
// BAD
|
|
166
|
+
let server = "192.168.1.100"
|
|
167
|
+
|
|
168
|
+
// GOOD
|
|
169
|
+
let server = "api.myapp.com"
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**Short permission descriptions:**
|
|
173
|
+
|
|
174
|
+
```xml
|
|
175
|
+
<!-- BAD -->
|
|
176
|
+
<key>NSCameraUsageDescription</key>
|
|
177
|
+
<string>Camera</string>
|
|
178
|
+
|
|
179
|
+
<!-- GOOD -->
|
|
180
|
+
<key>NSCameraUsageDescription</key>
|
|
181
|
+
<string>MyApp uses the camera to scan QR codes for quick login.</string>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Step 5: Re-scan and Track Progress
|
|
185
|
+
|
|
186
|
+
After fixing issues, run the scan again:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
ios-app-review scan /path/to/MyApp.xcodeproj --save-history
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
On subsequent scans with `--save-history`, you can compare progress:
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
ios-app-review scan /path/to/MyApp.xcodeproj --save-history
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Use the `view_scan_history` MCP tool or compare scans to see your score trend over time.
|
|
199
|
+
|
|
200
|
+
## Step 6: Set Up as MCP Server (Optional)
|
|
201
|
+
|
|
202
|
+
To use the plugin from Claude Code as an MCP server, add to `~/.claude/mcp_servers.json`:
|
|
203
|
+
|
|
204
|
+
```json
|
|
205
|
+
{
|
|
206
|
+
"ios-app-review": {
|
|
207
|
+
"command": "node",
|
|
208
|
+
"args": ["/path/to/ios-app-review-plugin/dist/index.js"]
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Then in Claude Code, simply ask:
|
|
214
|
+
|
|
215
|
+
```
|
|
216
|
+
Analyze my iOS app at /path/to/MyApp.xcodeproj for App Store compliance
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Claude will call the `analyze_ios_app` tool and present the results conversationally.
|
|
220
|
+
|
|
221
|
+
## Next Steps
|
|
222
|
+
|
|
223
|
+
- [CI Integration Tutorial](./CI_INTEGRATION.md) -- Automate scans in your build pipeline
|
|
224
|
+
- [Custom Rules Tutorial](./CUSTOM_RULES.md) -- Add team-specific checks
|
|
225
|
+
- [ASC Setup Tutorial](./ASC_SETUP.md) -- Validate App Store Connect metadata
|
|
226
|
+
- [Analyzers Reference](../ANALYZERS.md) -- Full list of checks performed
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Video Script: Introduction to iOS App Review Plugin
|
|
2
|
+
|
|
3
|
+
**Duration:** 3 minutes
|
|
4
|
+
**Audience:** iOS developers who submit apps to the App Store
|
|
5
|
+
**Goal:** Explain the problem, show the tool, and demonstrate a first scan
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Opening (0:00 - 0:30)
|
|
10
|
+
|
|
11
|
+
**Hook:** "If you have ever had an app rejected by Apple, you know the frustration. A single missing privacy description or a leftover debug URL can cost you days."
|
|
12
|
+
|
|
13
|
+
**Problem statement:**
|
|
14
|
+
- App Store rejections are time-consuming.
|
|
15
|
+
- Apple checks dozens of criteria: privacy manifests, deprecated APIs, metadata completeness, icon sizes, security patterns.
|
|
16
|
+
- Manual checks are error-prone and tedious.
|
|
17
|
+
|
|
18
|
+
**Transition:** "The iOS App Review Plugin automates these checks before you submit."
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## What It Does (0:30 - 1:15)
|
|
23
|
+
|
|
24
|
+
**Overview narration with on-screen text/graphics:**
|
|
25
|
+
|
|
26
|
+
The plugin is two things:
|
|
27
|
+
1. A CLI tool you run locally or in CI.
|
|
28
|
+
2. An MCP server that integrates with Claude Code.
|
|
29
|
+
|
|
30
|
+
**On screen: Show the architecture diagram.**
|
|
31
|
+
|
|
32
|
+
It runs 12 analyzers across two domains:
|
|
33
|
+
|
|
34
|
+
**Codebase (8 analyzers):**
|
|
35
|
+
- Info.plist validation
|
|
36
|
+
- Privacy manifest (iOS 17+)
|
|
37
|
+
- Entitlements
|
|
38
|
+
- Code scanning (secrets, debug code, IPv6)
|
|
39
|
+
- Deprecated APIs
|
|
40
|
+
- Private APIs
|
|
41
|
+
- Security vulnerabilities
|
|
42
|
+
- UI/UX compliance (icons, launch screen, accessibility)
|
|
43
|
+
|
|
44
|
+
**App Store Connect (4 analyzers):**
|
|
45
|
+
- Metadata completeness
|
|
46
|
+
- Screenshot validation
|
|
47
|
+
- Version comparison
|
|
48
|
+
- In-app purchase readiness
|
|
49
|
+
|
|
50
|
+
**Transition:** "Let me show you what it looks like in practice."
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Demo: First Scan (1:15 - 2:30)
|
|
55
|
+
|
|
56
|
+
**Terminal recording:**
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# Install
|
|
60
|
+
npm install -g ios-app-review-plugin
|
|
61
|
+
|
|
62
|
+
# Run a scan
|
|
63
|
+
ios-app-review scan ./SampleApp.xcodeproj
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Narrate the output as it appears:**
|
|
67
|
+
|
|
68
|
+
1. "The report starts with a readiness score -- 68 out of 100."
|
|
69
|
+
2. "The summary shows 2 errors, 5 warnings, and 3 info items."
|
|
70
|
+
3. "Priority Remediation lists the errors that will most likely cause rejection."
|
|
71
|
+
4. "Scrolling down, issues are grouped by category."
|
|
72
|
+
5. "Each issue includes the file, line number, Apple guideline reference, and a fix suggestion."
|
|
73
|
+
|
|
74
|
+
**Show fixing one issue:**
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# The scan found a hardcoded API key
|
|
78
|
+
# Fix it, then re-scan
|
|
79
|
+
ios-app-review scan ./SampleApp.xcodeproj
|
|
80
|
+
# Score improved to 78/100
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## What's Next (2:30 - 3:00)
|
|
86
|
+
|
|
87
|
+
**Closing narration:**
|
|
88
|
+
|
|
89
|
+
- "You can run this in CI to block PRs with errors."
|
|
90
|
+
- "Add --include-asc to validate your App Store Connect metadata too."
|
|
91
|
+
- "Custom rules let you enforce your team's own conventions."
|
|
92
|
+
- "Check the docs for setup guides on GitHub Actions, Fastlane, Bitrise, and Xcode Cloud."
|
|
93
|
+
|
|
94
|
+
**Call to action:**
|
|
95
|
+
- Link to GitHub repository
|
|
96
|
+
- Link to Getting Started tutorial
|
|
97
|
+
- "Star the repo if you find it useful."
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Production Notes
|
|
102
|
+
|
|
103
|
+
- Use a real sample project with deliberate issues for the demo.
|
|
104
|
+
- Terminal should use a large font (24pt+) with dark background.
|
|
105
|
+
- Highlight key parts of the output with colored overlays.
|
|
106
|
+
- Keep the pace brisk -- this is a 3-minute overview, not a deep dive.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Video Script: CLI Usage
|
|
2
|
+
|
|
3
|
+
**Duration:** 2 minutes
|
|
4
|
+
**Audience:** Developers who have installed the plugin and want to learn the CLI
|
|
5
|
+
**Goal:** Cover the main CLI options through practical examples
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Opening (0:00 - 0:15)
|
|
10
|
+
|
|
11
|
+
"Let me walk through the CLI options you will use most often. The tool has one main command: scan."
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Basic Scan (0:15 - 0:35)
|
|
16
|
+
|
|
17
|
+
**Terminal:**
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
ios-app-review scan ./MyApp.xcodeproj
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
"By default, this runs all 8 core analyzers and prints a Markdown report to the terminal."
|
|
24
|
+
|
|
25
|
+
"The exit code is 0 for pass, 1 for errors found."
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Output Formats (0:35 - 0:55)
|
|
30
|
+
|
|
31
|
+
**Terminal:**
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# JSON for CI parsing
|
|
35
|
+
ios-app-review scan ./MyApp.xcodeproj --format json --output report.json
|
|
36
|
+
|
|
37
|
+
# HTML for sharing with the team
|
|
38
|
+
ios-app-review scan ./MyApp.xcodeproj --format html --output report.html
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
"JSON is best for CI pipelines. HTML gives you a styled report with dark mode support and collapsible sections."
|
|
42
|
+
|
|
43
|
+
**Quick flash of the HTML report in a browser.**
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Selective Analyzers (0:55 - 1:10)
|
|
48
|
+
|
|
49
|
+
**Terminal:**
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Only run code and security checks
|
|
53
|
+
ios-app-review scan ./MyApp.xcodeproj --analyzers code,security
|
|
54
|
+
|
|
55
|
+
# Only check privacy manifest
|
|
56
|
+
ios-app-review scan ./MyApp.xcodeproj --analyzers privacy
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
"Use --analyzers with a comma-separated list to focus on specific areas. Useful when you are working on a targeted fix."
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Incremental Scanning (1:10 - 1:25)
|
|
64
|
+
|
|
65
|
+
**Terminal:**
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# Only scan files changed since main branch
|
|
69
|
+
ios-app-review scan ./MyApp.xcodeproj --changed-since main
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
"This is the key option for CI. It scans only the files you changed, so PR checks run in seconds instead of minutes on large projects."
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Badge and History (1:25 - 1:40)
|
|
77
|
+
|
|
78
|
+
**Terminal:**
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
ios-app-review scan ./MyApp.xcodeproj --badge --save-history
|
|
82
|
+
|
|
83
|
+
# badge.svg is created
|
|
84
|
+
# Scan is saved for future comparison
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
"The --badge flag generates an SVG badge you can embed in your README. The --save-history flag persists the scan so you can track your score over time."
|
|
88
|
+
|
|
89
|
+
**Show the badge image.**
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## ASC Validation (1:40 - 1:55)
|
|
94
|
+
|
|
95
|
+
**Terminal:**
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
export ASC_KEY_ID="..."
|
|
99
|
+
export ASC_ISSUER_ID="..."
|
|
100
|
+
export ASC_PRIVATE_KEY_PATH="..."
|
|
101
|
+
|
|
102
|
+
ios-app-review scan ./MyApp.xcodeproj --include-asc
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
"Add --include-asc to also validate your App Store Connect metadata, screenshots, and in-app purchases. You need an API key from App Store Connect."
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Closing (1:55 - 2:00)
|
|
110
|
+
|
|
111
|
+
"That covers the main CLI options. For the full reference, check docs/CLI.md in the repository."
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Production Notes
|
|
116
|
+
|
|
117
|
+
- All commands should be executed live (not simulated).
|
|
118
|
+
- Use a sample project that produces diverse output.
|
|
119
|
+
- Split-screen: terminal on left, brief explanation text on right.
|
|
120
|
+
- Keep each section snappy -- under 20 seconds per option.
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# Video Script: CI Integration
|
|
2
|
+
|
|
3
|
+
**Duration:** 5 minutes
|
|
4
|
+
**Audience:** iOS developers setting up automated review checks in CI
|
|
5
|
+
**Goal:** Walk through GitHub Actions setup end-to-end, then briefly cover other platforms
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Opening (0:00 - 0:20)
|
|
10
|
+
|
|
11
|
+
"Catching App Store issues before they reach code review saves everyone time. In this video, I will set up automated review checks in GitHub Actions from scratch, then show how to adapt this for Fastlane, Bitrise, and Xcode Cloud."
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Part 1: GitHub Actions (0:20 - 3:00)
|
|
16
|
+
|
|
17
|
+
### Create the Workflow (0:20 - 0:50)
|
|
18
|
+
|
|
19
|
+
**Editor (VS Code or similar):**
|
|
20
|
+
|
|
21
|
+
"Create a new file at .github/workflows/app-review.yml."
|
|
22
|
+
|
|
23
|
+
```yaml
|
|
24
|
+
name: App Store Review Check
|
|
25
|
+
on:
|
|
26
|
+
pull_request:
|
|
27
|
+
branches: [main]
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
"This triggers on pull requests to main."
|
|
31
|
+
|
|
32
|
+
### Add the Job (0:50 - 1:30)
|
|
33
|
+
|
|
34
|
+
```yaml
|
|
35
|
+
jobs:
|
|
36
|
+
review-check:
|
|
37
|
+
runs-on: macos-latest
|
|
38
|
+
steps:
|
|
39
|
+
- uses: actions/checkout@v4
|
|
40
|
+
with:
|
|
41
|
+
fetch-depth: 0
|
|
42
|
+
|
|
43
|
+
- uses: actions/setup-node@v4
|
|
44
|
+
with:
|
|
45
|
+
node-version: '20'
|
|
46
|
+
|
|
47
|
+
- name: Install ios-app-review
|
|
48
|
+
run: npm install -g ios-app-review-plugin
|
|
49
|
+
|
|
50
|
+
- name: Run review check
|
|
51
|
+
run: |
|
|
52
|
+
ios-app-review scan ./MyApp.xcodeproj \
|
|
53
|
+
--format json \
|
|
54
|
+
--output report.json
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
"fetch-depth 0 gives us full git history, which we need for incremental scanning."
|
|
58
|
+
|
|
59
|
+
### Add Artifact Upload (1:30 - 1:50)
|
|
60
|
+
|
|
61
|
+
```yaml
|
|
62
|
+
- name: Upload report
|
|
63
|
+
if: always()
|
|
64
|
+
uses: actions/upload-artifact@v4
|
|
65
|
+
with:
|
|
66
|
+
name: review-report
|
|
67
|
+
path: report.json
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
"'if: always()' ensures the report is uploaded even when the check fails."
|
|
71
|
+
|
|
72
|
+
### Push and Test (1:50 - 2:15)
|
|
73
|
+
|
|
74
|
+
**Terminal:**
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
git add .github/workflows/app-review.yml
|
|
78
|
+
git commit -m "Add App Store review CI check"
|
|
79
|
+
git push
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
"Now I will open a PR to trigger it."
|
|
83
|
+
|
|
84
|
+
**Show GitHub PR checks tab with the workflow running. Show it completing with pass or fail.**
|
|
85
|
+
|
|
86
|
+
### Add Incremental Scanning (2:15 - 2:35)
|
|
87
|
+
|
|
88
|
+
"For faster PR checks, scan only changed files:"
|
|
89
|
+
|
|
90
|
+
```yaml
|
|
91
|
+
- name: Incremental scan
|
|
92
|
+
run: |
|
|
93
|
+
ios-app-review scan ./MyApp.xcodeproj \
|
|
94
|
+
--changed-since origin/main \
|
|
95
|
+
--format json \
|
|
96
|
+
--output report.json
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
"This typically finishes in under 5 seconds."
|
|
100
|
+
|
|
101
|
+
### Make It a Required Check (2:35 - 3:00)
|
|
102
|
+
|
|
103
|
+
**Browser -- GitHub Settings:**
|
|
104
|
+
|
|
105
|
+
1. Settings > Branches > Branch protection rules
|
|
106
|
+
2. Edit rule for `main`
|
|
107
|
+
3. Enable "Require status checks"
|
|
108
|
+
4. Select "App Store Review Check"
|
|
109
|
+
|
|
110
|
+
"Now PRs cannot merge until the review check passes."
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Part 2: Other Platforms (3:00 - 4:30)
|
|
115
|
+
|
|
116
|
+
### Fastlane (3:00 - 3:30)
|
|
117
|
+
|
|
118
|
+
**Editor:**
|
|
119
|
+
|
|
120
|
+
```ruby
|
|
121
|
+
# fastlane/Fastfile
|
|
122
|
+
lane :review_check do
|
|
123
|
+
sh("ios-app-review scan ../MyApp.xcodeproj --format json --output ../report.json")
|
|
124
|
+
|
|
125
|
+
report = JSON.parse(File.read("../report.json"))
|
|
126
|
+
if report["summary"]["errors"] > 0
|
|
127
|
+
UI.user_error!("Review check failed")
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
lane :release do
|
|
132
|
+
review_check # gate before submit
|
|
133
|
+
build_app
|
|
134
|
+
upload_to_app_store
|
|
135
|
+
end
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
"Put it before upload_to_app_store so it gates your release lane."
|
|
139
|
+
|
|
140
|
+
### Bitrise (3:30 - 3:55)
|
|
141
|
+
|
|
142
|
+
**Editor:**
|
|
143
|
+
|
|
144
|
+
```yaml
|
|
145
|
+
- script@1:
|
|
146
|
+
title: Run ios-app-review
|
|
147
|
+
inputs:
|
|
148
|
+
- content: |
|
|
149
|
+
npm install -g ios-app-review-plugin
|
|
150
|
+
ios-app-review scan ./MyApp.xcodeproj \
|
|
151
|
+
--format json \
|
|
152
|
+
--output "$BITRISE_DEPLOY_DIR/report.json"
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
"Bitrise deploys the report artifact automatically with the deploy-to-bitrise-io step."
|
|
156
|
+
|
|
157
|
+
### Xcode Cloud (3:55 - 4:20)
|
|
158
|
+
|
|
159
|
+
**Editor:**
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
# ci_scripts/ci_post_clone.sh
|
|
163
|
+
#!/bin/bash
|
|
164
|
+
set -e
|
|
165
|
+
brew install node 2>/dev/null || true
|
|
166
|
+
npm install -g ios-app-review-plugin
|
|
167
|
+
ios-app-review scan "$CI_PRIMARY_REPOSITORY_PATH/MyApp.xcodeproj" \
|
|
168
|
+
--format json --output "$CI_PRIMARY_REPOSITORY_PATH/report.json"
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
"Xcode Cloud runs scripts in the ci_scripts directory automatically. Just make it executable and commit it."
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Part 3: Best Practices (4:20 - 4:50)
|
|
176
|
+
|
|
177
|
+
"Quick tips from running this in production:"
|
|
178
|
+
|
|
179
|
+
1. "Use incremental scanning on PRs, full scans on main."
|
|
180
|
+
2. "Save history on main branch pushes to track your score over time."
|
|
181
|
+
3. "Start with errors-only blocking. The tool already only returns exit code 1 for errors, not warnings."
|
|
182
|
+
4. "Cache node_modules to speed up installs."
|
|
183
|
+
5. "Keep ASC credentials in your CI platform's secrets manager."
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Closing (4:50 - 5:00)
|
|
188
|
+
|
|
189
|
+
"That is CI integration in 5 minutes. All of these configurations are in the docs/CI_CD.md file in the repository. Check the links in the description."
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Production Notes
|
|
194
|
+
|
|
195
|
+
- Pre-record the GitHub Actions run to avoid waiting on CI during the video.
|
|
196
|
+
- Show the actual PR checks UI -- green check or red X.
|
|
197
|
+
- For the Fastlane/Bitrise/Xcode Cloud sections, show the config file briefly (10-15 seconds each).
|
|
198
|
+
- End card: link to repo, docs, and the Getting Started tutorial.
|
package/eslint.config.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
const typescript = require('@typescript-eslint/eslint-plugin');
|
|
2
|
+
const parser = require('@typescript-eslint/parser');
|
|
3
|
+
|
|
4
|
+
module.exports = [
|
|
5
|
+
{
|
|
6
|
+
files: ['src/**/*.ts'],
|
|
7
|
+
languageOptions: {
|
|
8
|
+
parser: parser,
|
|
9
|
+
parserOptions: {
|
|
10
|
+
ecmaVersion: 2022,
|
|
11
|
+
sourceType: 'module',
|
|
12
|
+
project: './tsconfig.json',
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
plugins: {
|
|
16
|
+
'@typescript-eslint': typescript,
|
|
17
|
+
},
|
|
18
|
+
rules: {
|
|
19
|
+
...typescript.configs['recommended'].rules,
|
|
20
|
+
'@typescript-eslint/explicit-function-return-type': 'warn',
|
|
21
|
+
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
|
|
22
|
+
'@typescript-eslint/no-explicit-any': 'error',
|
|
23
|
+
'@typescript-eslint/prefer-nullish-coalescing': 'warn',
|
|
24
|
+
'@typescript-eslint/prefer-optional-chain': 'warn',
|
|
25
|
+
'no-console': ['warn', { allow: ['warn', 'error'] }],
|
|
26
|
+
'eqeqeq': ['error', 'always'],
|
|
27
|
+
'curly': ['error', 'all'],
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
ignores: ['dist/**', 'node_modules/**', 'coverage/**', '*.js'],
|
|
32
|
+
},
|
|
33
|
+
];
|