@mcamdali/sdkbump 0.0.0-stage → 0.1.3
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/LICENSE +21 -0
- package/README.de.md +251 -0
- package/README.es.md +252 -0
- package/README.fr.md +252 -0
- package/README.ja.md +250 -0
- package/README.ko.md +250 -0
- package/README.md +322 -2
- package/README.pt-BR.md +252 -0
- package/README.ru.md +252 -0
- package/README.tr.md +338 -0
- package/README.zh-CN.md +250 -0
- package/dist/cli/main.d.ts +2 -0
- package/dist/cli/main.js +11 -0
- package/dist/cli/run.d.ts +29 -0
- package/dist/cli/run.js +111 -0
- package/dist/collect/app.d.ts +48 -0
- package/dist/collect/app.js +117 -0
- package/dist/collect/blank.d.ts +6 -0
- package/dist/collect/blank.js +75 -0
- package/dist/collect/pbxproj.d.ts +45 -0
- package/dist/collect/pbxproj.js +260 -0
- package/dist/collect/plist-binary.d.ts +2 -0
- package/dist/collect/plist-binary.js +123 -0
- package/dist/collect/plist-value.d.ts +15 -0
- package/dist/collect/plist-value.js +14 -0
- package/dist/collect/plist-xml.d.ts +2 -0
- package/dist/collect/plist-xml.js +195 -0
- package/dist/collect/plist.d.ts +6 -0
- package/dist/collect/plist.js +19 -0
- package/dist/collect/regions.d.ts +9 -0
- package/dist/collect/regions.js +108 -0
- package/dist/collect/sources.d.ts +45 -0
- package/dist/collect/sources.js +99 -0
- package/dist/core/files.d.ts +22 -0
- package/dist/core/files.js +47 -0
- package/dist/core/lines.d.ts +2 -0
- package/dist/core/lines.js +21 -0
- package/dist/core/versions.d.ts +18 -0
- package/dist/core/versions.js +63 -0
- package/dist/detect/project.d.ts +46 -0
- package/dist/detect/project.js +220 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +27 -0
- package/dist/model.d.ts +93 -0
- package/dist/model.js +2 -0
- package/dist/report/index.d.ts +12 -0
- package/dist/report/index.js +22 -0
- package/dist/report/markdown.d.ts +2 -0
- package/dist/report/markdown.js +113 -0
- package/dist/report/text.d.ts +27 -0
- package/dist/report/text.js +63 -0
- package/dist/report/tty.d.ts +7 -0
- package/dist/report/tty.js +112 -0
- package/dist/rules/check.d.ts +11 -0
- package/dist/rules/check.js +253 -0
- package/dist/rules/data.d.ts +217 -0
- package/dist/rules/data.js +141 -0
- package/dist/rules/fixes.d.ts +28 -0
- package/dist/rules/fixes.js +161 -0
- package/dist/rules/patterns.d.ts +29 -0
- package/dist/rules/patterns.js +109 -0
- package/dist/rules/query.d.ts +16 -0
- package/dist/rules/query.js +50 -0
- package/dist/scan.d.ts +10 -0
- package/dist/scan.js +115 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +7 -0
- package/package.json +69 -4
- package/rules/ios27.json +613 -0
- package/rules/schema.json +449 -0
package/README.fr.md
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
<!-- i18n-source: README.md@49073c524eb2b7aad433b6794961ec40869c1170 status=reviewed -->
|
|
2
|
+
<!-- brand:start -->
|
|
3
|
+
|
|
4
|
+
<p align="center"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/banner-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/banner-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/banner-light.svg" alt="sdkbump: Checks native iOS, Flutter and React Native apps for the iOS 27 SDK changes and names the fix for each."></picture></p>
|
|
5
|
+
|
|
6
|
+
<!-- lang-selector:start -->
|
|
7
|
+
<p align="center"><a href="README.md">English</a> · <a href="README.tr.md">Türkçe</a> · <a href="README.zh-CN.md">简体中文</a> · <a href="README.ja.md">日本語</a> · <a href="README.ko.md">한국어</a> · <a href="README.es.md">Español</a> · <a href="README.de.md">Deutsch</a> · <a href="README.fr.md">Français</a> · <a href="README.pt-BR.md">Português (Brasil)</a> · <a href="README.ru.md">Русский</a></p>
|
|
8
|
+
<!-- lang-selector:end -->
|
|
9
|
+
|
|
10
|
+
<p align="center">
|
|
11
|
+
<a href="https://github.com/muhittincamdali/sdkbump/actions/workflows/ci.yml"><img src="https://github.com/muhittincamdali/sdkbump/actions/workflows/ci.yml/badge.svg" alt="État de la CI"></a>
|
|
12
|
+
<a href="https://github.com/muhittincamdali/sdkbump/releases"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-version-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-version-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-version-light.svg" alt="Dernière version: v0.1.2"></picture></a>
|
|
13
|
+
<a href="https://github.com/muhittincamdali/sdkbump/blob/main/package.json"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-language-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-language-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-language-light.svg" alt="Version du langage: Node.js 22.12+"></picture></a>
|
|
14
|
+
<a href="https://github.com/muhittincamdali/sdkbump/blob/main/LICENSE"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-license-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-license-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-license-light.svg" alt="Licence: MIT"></picture></a>
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
<p align="center">
|
|
18
|
+
<a href="#démarrage-rapide"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-start-fr-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-start-fr-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-start-fr-light.svg" alt="Commencer"></picture></a>
|
|
19
|
+
<a href="https://muhittincamdali.github.io/sdkbump/"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-docs-fr-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-docs-fr-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-docs-fr-light.svg" alt="Documentation"></picture></a>
|
|
20
|
+
<a href="https://github.com/muhittincamdali/sdkbump/tree/main/docs/guides"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-guides-fr-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-guides-fr-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-guides-fr-light.svg" alt="Guides"></picture></a>
|
|
21
|
+
<a href="https://github.com/muhittincamdali/sdkbump/tree/main/examples"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-examples-fr-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-examples-fr-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-examples-fr-light.svg" alt="Exemples"></picture></a>
|
|
22
|
+
</p>
|
|
23
|
+
|
|
24
|
+
> Ceci est une traduction du README anglais. En cas de différence, la version anglaise fait foi.
|
|
25
|
+
|
|
26
|
+
<!-- brand:end -->
|
|
27
|
+
|
|
28
|
+
Avant de livrer une version compilée avec Xcode 27 : sdkbump analyse un projet iOS natif, Flutter ou React Native/Expo pour repérer ce que change le SDK iOS 27, à commencer par le cycle de vie UIScene, et vous indique quelle correction s'applique à chaque constat. Il lit les fichiers de votre projet ; il ne compile, n'exécute ni ne modifie rien.
|
|
29
|
+
|
|
30
|
+
<picture><source media="(prefers-color-scheme: dark)" srcset="docs/media/demo-rn-087-dark.svg"><source media="(prefers-color-scheme: light)" srcset="docs/media/demo-rn-087-light.svg"><img src="docs/media/demo-rn-087-light.svg" alt="sdkbump exécuté sur une app React Native 0.87 : ne se lance pas lorsqu'elle est compilée avec le SDK iOS 27 ; SCN001 aucune configuration de scène et SCN002 fenêtre créée dans l'app delegate, avec trois façons de corriger"></picture>
|
|
31
|
+
|
|
32
|
+
<sub>Enregistré avec la vraie CLI sur le <a href="fixtures/rn-087">fixture rn-087</a>, une app React
|
|
33
|
+
Native 0.87.1 créée avec <code>@react-native-community/cli init</code> (<code>npm run demo</code>).</sub>
|
|
34
|
+
|
|
35
|
+
## Points forts
|
|
36
|
+
|
|
37
|
+
- **Répond à « va-t-elle se lancer ? »** Une app qui ne déclare aucune scène se compile avec Xcode 27, puis s'arrête au lancement. sdkbump vous le dit avant que vous ne le découvriez sur un appareil de test, et nomme les fichiers à modifier.
|
|
38
|
+
- **Natif, Flutter, React Native et Expo** dans un seul rapport, avec les mêmes identifiants de règle, en texte, Markdown ou JSON, et avec un code de sortie pour la CI.
|
|
39
|
+
- **La correction qui s'applique à votre projet** : React Native 0.88 ou un scene delegate écrit à la main, l'activation optionnelle d'Expo SDK 57 ou SDK 58, la migration automatique de Flutter ou les étapes manuelles (sdkbump vérifie les mêmes conditions que le migrateur de Flutter), ou l'API SwiftUI pour une app SwiftUI.
|
|
40
|
+
- **Les ruptures silencieuses aussi** : les méthodes de l'app delegate et les options de lancement qu'UIKit cesse d'utiliser dès que l'app a une scène (liens, Handoff, actions rapides, passages au premier plan et en arrière-plan), et les recherches de fenêtre qui ne trouvent plus la bonne fenêtre.
|
|
41
|
+
- **Chaque affirmation a une source.** Les règles sont des données ([rules/ios27.json](rules/ios27.json)) et chacune cite les pages d'Apple, de Flutter, de React Native ou d'Expo ; les tests échouent si l'une d'elles n'en cite aucune.
|
|
42
|
+
- **Vérifié dans le simulateur iOS 27** : l'échec au lancement et l'écran noir derrière SCN001 et SCN002 ont été reproduits avec Xcode 27.0, et les enregistrements sont dans le dépôt.
|
|
43
|
+
|
|
44
|
+
## Démarrage rapide
|
|
45
|
+
|
|
46
|
+
Il vous faut [Node.js](https://nodejs.org/) 22.12 ou ultérieur (`node --version` affiche la version ; sur un Mac, `brew install node` l'installe). Rien d'autre.
|
|
47
|
+
|
|
48
|
+
**1. Ouvrez un terminal dans le dossier de votre app**, celui qui contient le `.xcodeproj`, le `pubspec.yaml` ou le `package.json` :
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
cd path/to/YourApp
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**2. Lancez sdkbump :**
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
npx @mcamdali/sdkbump
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Le paquet npm s'appelle `@mcamdali/sdkbump` ; la commande qu'il installe s'appelle `sdkbump`. Un `npx sdkbump` sans scope ne l'exécute pas.
|
|
61
|
+
|
|
62
|
+
**3. Lisez la première ligne sous le nom de votre projet.** « Fails to launch when built with the iOS 27 SDK » (ne se lance pas lorsqu'elle est compilée avec le SDK iOS 27) signifie que l'app s'arrête au lancement tant que vous n'avez pas corrigé les constats **ERROR** ; chacun indique quelle correction de la liste « How to fix » s'applique. Les constats **WARNING** n'empêchent pas le lancement, mais cessent de fonctionner dès que l'app a une scène. « Launch not determined » (lancement non déterminé) signifie que sdkbump n'a pas pu lire un Info.plist ; les notes à la fin du rapport indiquent lequel et pourquoi (voir Limites plus bas).
|
|
63
|
+
|
|
64
|
+
## Ce qui change quand vous compilez avec le SDK iOS 27
|
|
65
|
+
|
|
66
|
+
Extrait de la page d'Apple
|
|
67
|
+
[Transitioning to the UIKit scene-based life cycle](https://developer.apple.com/documentation/uikit/transitioning-to-the-uikit-scene-based-life-cycle) (traduction) :
|
|
68
|
+
|
|
69
|
+
> À partir d'iOS 27, d'iPadOS 27, de Mac Catalyst 27, de tvOS 27 et de visionOS 27, les apps compilées avec le dernier SDK doivent adopter le cycle de vie basé sur les scènes, sinon elles ne se lancent pas.
|
|
70
|
+
|
|
71
|
+
1. **L'app s'arrête au lancement si elle ne déclare aucune scène.** Pas de `UIApplicationSceneManifest` avec une configuration dans l'Info.plist et pas de `application(_:configurationForConnecting:options:)` : UIKit met fin au processus avec le message « UIScene life cycle is required for apps built with this SDK ». Le compilateur n'avertit pas, car la vérification a lieu au démarrage de l'app. React Native 0.87 et antérieur, Expo SDK 57 sans son activation optionnelle et Expo SDK 56 et antérieur créent des apps de ce type ; c'est aussi le cas des apps Flutter que l'outil Flutter ne peut pas migrer.
|
|
72
|
+
2. **Avec une scène, l'app delegate ne reçoit plus les événements d'interface.** Les liens, les user activities, les actions rapides et les transitions actif/arrière-plan vont au scene delegate, et une fenêtre créée par l'app delegate n'est jamais affichée.
|
|
73
|
+
|
|
74
|
+
[Pourquoi ça compile et plante quand même](docs/guides/why-it-crashes.md) présente la [matrice de lancement](examples/launch-matrix/README.md) que nous avons exécutée dans le simulateur iOS 27.0.
|
|
75
|
+
|
|
76
|
+
## Ce que sdkbump vérifie
|
|
77
|
+
|
|
78
|
+
| Règle | Gravité | Constat | Observé dans le simulateur iOS 27.0 |
|
|
79
|
+
| ------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------- |
|
|
80
|
+
| SCN001 | error | Aucune configuration de scène : pas de `UIApplicationSceneManifest` configuré, pas de `configurationForConnecting`, pas une `App` SwiftUI ; pour Expo sans `ios/`, la version du SDK et `enableSceneSupport` | s'arrête au lancement |
|
|
81
|
+
| SCN002 | error | L'app delegate crée la fenêtre avec `UIWindow(frame:)` | écran noir dès que l'app a une scène |
|
|
82
|
+
| SCN003 | warning | Méthodes de l'app delegate et clés d'options de lancement qu'UIKit n'utilise plus avec les scènes (13 au total), sauf si le scene delegate les gère déjà | `applicationDidEnterBackground(_:)` n'est pas appelée dans une app SwiftUI |
|
|
83
|
+
| SCN004 | warning | Recherches de fenêtre via `UIApplication.shared.keyWindow`, `.windows` ou le `window` de l'app delegate | uniquement des avertissements de dépréciation du compilateur |
|
|
84
|
+
|
|
85
|
+
Données de règles `ios27@2026.10.15`, vérifiées avec Xcode 27.0 (27A266a). Lorsque React Native ou Expo a `react-native-uiscene-bridge` ou `react-native-xcode27` installé, les constats qu'il gère à l'exécution sont affichés comme gérés, avec les limites indiquées dans son README, et ne font pas échouer l'exécution.
|
|
86
|
+
|
|
87
|
+
## Installation
|
|
88
|
+
|
|
89
|
+
Installez la commande `sdkbump` depuis npm (paquet `@mcamdali/sdkbump`) :
|
|
90
|
+
|
|
91
|
+
```sh
|
|
92
|
+
npm i -g @mcamdali/sdkbump
|
|
93
|
+
sdkbump
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Dans un projet, `npm install --save-dev @mcamdali/sdkbump` épingle une version, puis `npx sdkbump` exécute cette copie. Chaque [version GitHub](https://github.com/muhittincamdali/sdkbump/releases) contient aussi le même paquet sous le nom `sdkbump-<version>.tgz`, avec un fichier `SHA256SUMS` ; `npx` l'exécute depuis son URL sans passer par npm. Une formule Homebrew pour `muhittincamdali/tap` est préparée par le workflow de publication (prévue avec la première version du tap).
|
|
97
|
+
|
|
98
|
+
## Utilisation
|
|
99
|
+
|
|
100
|
+
```text
|
|
101
|
+
sdkbump [path] [options]
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
| Option | Ce qu'elle fait |
|
|
105
|
+
| ----------------------- | ---------------------------------------------------------------------------------- |
|
|
106
|
+
| `path` | Dossier du projet ou `.xcodeproj` ; par défaut, le dossier courant |
|
|
107
|
+
| `-f, --format <format>` | `tty` (par défaut), `markdown` ou `json` |
|
|
108
|
+
| `-o, --output <file>` | Écrit le rapport dans un fichier au lieu du terminal |
|
|
109
|
+
| `--fail-on <severity>` | `error` (par défaut), `warning`, `info` ou `none` : quand le code de sortie vaut 1 |
|
|
110
|
+
| `--no-color` | Texte brut même dans un terminal (`NO_COLOR` et `FORCE_COLOR` sont respectés) |
|
|
111
|
+
|
|
112
|
+
Codes de sortie : `0` aucun constat non géré au niveau de `--fail-on` ou au-dessus, `1` constats à ce niveau ou au-dessus, `2` arguments invalides, aucun projet iOS trouvé ou erreur inattendue.
|
|
113
|
+
|
|
114
|
+
sdkbump trouve seul l'app iOS : un `.xcodeproj` à la racine ou un dossier plus bas pour les apps natives, `ios/` pour les apps Flutter, React Native et Expo (`example/ios/` pour un plugin Flutter). Il lit chaque target d'app iOS du fichier de projet, l'Info.plist que chacune désigne (XML ou binaire) et les fichiers Swift et Objective-C de l'app, en ignorant Pods, `node_modules`, la sortie de compilation et les tests. Les apps Expo sans `ios/` sont vérifiées à partir de package.json et app.json.
|
|
115
|
+
|
|
116
|
+
### Conserver un rapport Markdown avec le code
|
|
117
|
+
|
|
118
|
+
```sh
|
|
119
|
+
npx @mcamdali/sdkbump --format markdown --output sdkbump.md
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Utiliser le rapport JSON dans des scripts
|
|
123
|
+
|
|
124
|
+
```sh
|
|
125
|
+
npx @mcamdali/sdkbump --format json > sdkbump.json
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Chaque constat a `rule`, `severity`, `file`, `line`, `message`, le `fix` avec ses étapes et son guide, `alternatives`, `mitigation` (renseigné lorsqu'un paquet de contournement le gère) et `sources`. La structure est `schemaVersion` 0 et peut changer avant la 1.0. [examples/shell/launch-blockers.sh](examples/shell/launch-blockers.sh) le filtre avec `jq`.
|
|
129
|
+
|
|
130
|
+
### L'exécuter en CI
|
|
131
|
+
|
|
132
|
+
[examples/github-actions/sdkbump.yml](examples/github-actions/sdkbump.yml) ajoute le rapport au résumé du job de chaque pull request qui touche à l'app iOS et fait échouer le job en cas d'erreurs.
|
|
133
|
+
|
|
134
|
+
### Depuis JavaScript
|
|
135
|
+
|
|
136
|
+
```js
|
|
137
|
+
import { render, scan } from 'sdkbump';
|
|
138
|
+
|
|
139
|
+
const report = await scan('path/to/app');
|
|
140
|
+
console.log(report.verdict.text);
|
|
141
|
+
console.log(render(report, 'markdown'));
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Une version exécutable se trouve dans [examples/api/verdicts.mjs](examples/api/verdicts.mjs).
|
|
145
|
+
|
|
146
|
+
## Démo
|
|
147
|
+
|
|
148
|
+
Les enregistrements du terminal proviennent de la CLI exécutée sur les [fixtures](fixtures/README.md), de vrais projets créés avec chaque toolchain :
|
|
149
|
+
|
|
150
|
+
| Projet | Enregistrement |
|
|
151
|
+
| ----------------------------------------------------------- | --------------------------------------------------------------------------------------- |
|
|
152
|
+
| App React Native 0.87.1 | en haut de cette page |
|
|
153
|
+
| App Flutter avec un AppDelegate personnalisé (Flutter 3.24) | [clair](docs/media/demo-flutter-light.svg) · [sombre](docs/media/demo-flutter-dark.svg) |
|
|
154
|
+
| App SwiftUI avec un app delegate par adaptateur | [clair](docs/media/demo-swiftui-light.svg) · [sombre](docs/media/demo-swiftui-dark.svg) |
|
|
155
|
+
|
|
156
|
+
Dans le simulateur iOS 27.0 (iPhone 17, compilé avec Xcode 27.0), le fixture UIKit natif s'arrête au lancement, et la même app migrée vers un scene delegate se lance :
|
|
157
|
+
|
|
158
|
+
<picture><source media="(prefers-color-scheme: dark)" srcset="docs/media/demo-simulator-native-uikit-dark.svg"><source media="(prefers-color-scheme: light)" srcset="docs/media/demo-simulator-native-uikit-light.svg"><img src="docs/media/demo-simulator-native-uikit-light.svg" alt="scripts/simulator-check.sh native-uikit dans le simulateur iOS 27.0 : ne s'exécute pas 4 secondes après le lancement, avec la ligne d'UIKit : Application failed to launch: UIScene life cycle is required for apps built with this SDK"></picture>
|
|
159
|
+
|
|
160
|
+
<p align="center"><img src="docs/media/simulator/launched.png" width="480" alt="Les fixtures native-uikit-scenes et native-swiftui s'exécutant dans un simulateur iPhone 17 sous iOS 27.0, compilés avec Xcode 27.0"></p>
|
|
161
|
+
|
|
162
|
+
Mesuré le 15 octobre 2026 sur un Mac (Apple silicon, M5 Max) avec Node.js 26.11 pendant que d'autres tâches tournaient dessus : trois séries de 100 exécutions de `node dist/cli/main.js` sur les dix fixtures, démarrage de Node.js compris. Les médianes des trois séries étaient de 0,11, 0,12 et 0,19 seconde ; l'exécution la plus lente a pris 0,33 seconde. Sur une machine plus chargée, les temps sont plus longs.
|
|
163
|
+
|
|
164
|
+
## Statut
|
|
165
|
+
|
|
166
|
+
| Fonctionnalité | Statut |
|
|
167
|
+
| ------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
|
|
168
|
+
| Détection des projets natifs, Flutter (app et exemple de plugin), React Native et Expo | fonctionne |
|
|
169
|
+
| SCN001 à SCN004 sur l'Info.plist et les sources Swift/Objective-C de l'app elle-même | fonctionne |
|
|
170
|
+
| Choix de la correction par écosystème et par version ; vérification de la migration automatique de Flutter ; paquets de contournement | fonctionne |
|
|
171
|
+
| Rapports terminal, Markdown et JSON ; codes de sortie de `--fail-on` | fonctionne |
|
|
172
|
+
| Dépendances : Pods, `node_modules` et sources des plugins Flutter, avec le nom du paquet | prévu (0.2) |
|
|
173
|
+
| Avis de contournement SCN005 comme règle à part entière ; DPT001 pour les deployment targets inférieurs à 15.0 | prévu (0.2) |
|
|
174
|
+
| `--verify` : compiler et lancer dans le simulateur iOS 27 depuis la CLI | prévu (0.3) |
|
|
175
|
+
| Arbres syntaxiques Swift/Objective-C au lieu de motifs ; vérifications des `.app` compilées ; dépréciations de SiriKit | prévu (0.5) |
|
|
176
|
+
| `fix --dry-run` pour les apps natives, sortie SARIF, GitHub Action | prévu (0.8) |
|
|
177
|
+
| Schéma de règles et structure JSON stables | prévu (1.0) |
|
|
178
|
+
|
|
179
|
+
## Limites
|
|
180
|
+
|
|
181
|
+
- **Des motifs, pas un compilateur.** Les règles sont des expressions régulières appliquées au texte Swift et Objective-C dont les commentaires et les chaînes sont effacés. Du code généré, caché derrière des macros ou écrit d'une façon inhabituelle peut être manqué ou détecté à tort. Les arbres syntaxiques sont prévus (0.5).
|
|
182
|
+
- **Uniquement les sources de l'app.** Les Pods, `node_modules`, les plugins Flutter et les autres dépendances ne sont pas lus : un plugin qui s'appuie sur des méthodes de l'app delegate qu'UIKit n'appelle plus n'est donc pas signalé. L'analyse des dépendances est prévue (0.2).
|
|
183
|
+
- **Réglages de build lus uniquement dans project.pbxproj.** sdkbump lit `INFOPLIST_FILE` et `GENERATE_INFOPLIST_FILE` dans le fichier de projet et remplace `$(SRCROOT)`, `$(PROJECT_DIR)`, `$(TARGET_NAME)` et `$(PRODUCT_NAME)`. Il ne lit pas les fichiers `.xcconfig`, ne remplace pas les autres réglages de build et ne lit pas un Info.plist situé hors du dossier du projet. Quand il ne peut pas lire l'Info.plist d'une cible, SCN001 est un constat de niveau info et le verdict est « Launch not determined » au lieu d'une supposition.
|
|
184
|
+
- **Pas de fichier de suppression.** Un constat ne peut pas être marqué comme examiné ; `--fail-on` décide quelles sévérités font échouer l'exécution.
|
|
185
|
+
- **Des fichiers seulement.** sdkbump ne compile pas et ne lance pas l'app ; `--verify` est prévu (0.3).
|
|
186
|
+
|
|
187
|
+
## Documentation
|
|
188
|
+
|
|
189
|
+
Référence de l'API et guides : [muhittincamdali.github.io/sdkbump](https://muhittincamdali.github.io/sdkbump/).
|
|
190
|
+
|
|
191
|
+
## Guides
|
|
192
|
+
|
|
193
|
+
- [Pourquoi ça compile et plante quand même](docs/guides/why-it-crashes.md)
|
|
194
|
+
- [Apps natives UIKit et SwiftUI](docs/guides/native-ios.md)
|
|
195
|
+
- [Flutter : un AppDelegate personnalisé et des plugins](docs/guides/flutter.md)
|
|
196
|
+
- [React Native avant 0.88 et Expo avant SDK 58](docs/guides/react-native-expo.md)
|
|
197
|
+
- [Auteurs de modules natifs : liens et notifications au démarrage à froid](docs/guides/native-module-authors.md)
|
|
198
|
+
|
|
199
|
+
## Outils apparentés
|
|
200
|
+
|
|
201
|
+
D'autres projets travaillent sur le même changement ; le bon choix dépend de ce dont vous avez besoin :
|
|
202
|
+
|
|
203
|
+
- [react-native-uiscene-bridge](https://github.com/Atomics-hub/react-native-uiscene-bridge) et [react-native-xcode27](https://github.com/Atomics-hub/react-native-xcode27) permettent à une app React Native ou Expo de se lancer sans modification du code, à l'exécution. Ils conviennent quand vous ne pouvez pas encore mettre à jour ; sdkbump les reconnaît.
|
|
204
|
+
- [auditor-uiscene](https://github.com/Anzell/auditor-uiscene) audite les apps Flutter et leurs plugins avec un script shell.
|
|
205
|
+
- Le migrateur propre à Flutter (`flutter build ios` à partir de la 3.41) migre une app Flutter non modifiée.
|
|
206
|
+
- [flutter_spm_doctor](https://pub.dev/packages/flutter_spm_doctor) vérifie les plugins Flutter.
|
|
207
|
+
|
|
208
|
+
## Prérequis
|
|
209
|
+
|
|
210
|
+
| Toolchain | Version minimale |
|
|
211
|
+
| --------- | ---------------- |
|
|
212
|
+
| Node.js | 22.12 |
|
|
213
|
+
|
|
214
|
+
sdkbump n'a pas besoin de Xcode : il lit des fichiers, il fonctionne donc aussi sous Linux. La CI exécute les tests sur Node.js 22 et 24 (Linux) ; en local, les 280 réussissent sur Node.js 22.23, 24.22 et 26.11 sur un Mac (Apple silicon). Les enregistrements du simulateur nécessitent un Mac avec Xcode 27 et ne font pas partie de la CI.
|
|
215
|
+
|
|
216
|
+
## Architecture
|
|
217
|
+
|
|
218
|
+
```text
|
|
219
|
+
path ─► detectProject native | flutter | react-native | expo; iOS folder; versions
|
|
220
|
+
─► collectApp iOS app targets from project.pbxproj, their Info.plist (XML or binary),
|
|
221
|
+
Swift and Objective-C sources with comments and strings blanked
|
|
222
|
+
─► checkApp SCN001…SCN004, fix per ecosystem and version, workaround packages
|
|
223
|
+
rules/ios27.json what each rule says, fixes, sources (validated with zod)
|
|
224
|
+
─► render tty | markdown | json
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
- Les motifs de détection sont des expressions régulières appliquées à du texte source dont les commentaires et les chaînes sont vidés, et, quand cela compte, ils ne comptent qu'à l'intérieur d'un app delegate ou d'un scene delegate.
|
|
228
|
+
- Les données de règles sont séparées du code et versionnées (`ios27@2026.10.15`) ; un test échoue lorsqu'une règle, une correction ou un contournement n'a pas de source.
|
|
229
|
+
- La CLI (`src/cli/`) se contente d'analyser les arguments, de choisir les couleurs et les largeurs, et de définir le code de sortie.
|
|
230
|
+
|
|
231
|
+
## Feuille de route
|
|
232
|
+
|
|
233
|
+
Voir le tableau [Statut](#statut) : la 0.2 ajoute les dépendances et les deployment targets, la 0.3 le lancement dans le simulateur depuis la CLI, la 0.5 les arbres syntaxiques et les vérifications de l'app compilée, la 0.8 les corrections et SARIF, la 1.0 un schéma stable. [CHANGELOG.md](CHANGELOG.md) liste ce que chaque version a changé.
|
|
234
|
+
|
|
235
|
+
## FAQ
|
|
236
|
+
|
|
237
|
+
**Mon app fonctionne aujourd'hui sous iOS 27. Est-elle concernée ?** Si elle a été compilée avec Xcode 26 ou antérieur, la vérification ne s'applique pas à cette compilation : lors de notre essai, le même code lié au SDK iOS 26 s'est lancé dans le simulateur iOS 27. Elle s'applique à votre prochaine compilation avec Xcode 27.
|
|
238
|
+
|
|
239
|
+
**sdkbump remplace-t-il les tests sur un appareil ?** Non. Il lit des fichiers. Les enregistrements du simulateur dans ce dépôt viennent du simulateur iOS 27.0 ; rien ici n'a été exécuté sur un appareil.
|
|
240
|
+
|
|
241
|
+
**Pourquoi un constat est-il « géré » ?** Un paquet de contournement dans package.json (react-native-uiscene-bridge ou react-native-xcode27) déclare une scène à l'exécution. L'app se lance, mais elle n'a toujours pas de prise en charge des scènes qui lui soit propre ; le rapport liste les limites du paquet et la vraie correction.
|
|
242
|
+
|
|
243
|
+
**sdkbump modifie-t-il mon projet ?** Non. Il le lit et n'écrit que le rapport que vous demandez.
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
## Contribuer
|
|
247
|
+
|
|
248
|
+
Les contributions sont les bienvenues. Lisez le [guide de contribution](CONTRIBUTING.md) et le [code de conduite](https://github.com/muhittincamdali/.github/blob/main/CODE_OF_CONDUCT.md) avant d’ouvrir une pull request. Signalez les problèmes de sécurité en privé, comme indiqué dans la [politique de sécurité](SECURITY.md).
|
|
249
|
+
|
|
250
|
+
## Licence
|
|
251
|
+
|
|
252
|
+
Publié sous licence MIT. Voir [LICENSE](LICENSE).
|
package/README.ja.md
ADDED
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
<!-- i18n-source: README.md@49073c524eb2b7aad433b6794961ec40869c1170 status=reviewed -->
|
|
2
|
+
<!-- brand:start -->
|
|
3
|
+
|
|
4
|
+
<p align="center"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/banner-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/banner-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/banner-light.svg" alt="sdkbump: Checks native iOS, Flutter and React Native apps for the iOS 27 SDK changes and names the fix for each."></picture></p>
|
|
5
|
+
|
|
6
|
+
<!-- lang-selector:start -->
|
|
7
|
+
<p align="center"><a href="README.md">English</a> · <a href="README.tr.md">Türkçe</a> · <a href="README.zh-CN.md">简体中文</a> · <a href="README.ja.md">日本語</a> · <a href="README.ko.md">한국어</a> · <a href="README.es.md">Español</a> · <a href="README.de.md">Deutsch</a> · <a href="README.fr.md">Français</a> · <a href="README.pt-BR.md">Português (Brasil)</a> · <a href="README.ru.md">Русский</a></p>
|
|
8
|
+
<!-- lang-selector:end -->
|
|
9
|
+
|
|
10
|
+
<p align="center">
|
|
11
|
+
<a href="https://github.com/muhittincamdali/sdkbump/actions/workflows/ci.yml"><img src="https://github.com/muhittincamdali/sdkbump/actions/workflows/ci.yml/badge.svg" alt="CI ステータス"></a>
|
|
12
|
+
<a href="https://github.com/muhittincamdali/sdkbump/releases"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-version-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-version-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-version-light.svg" alt="最新バージョン: v0.1.2"></picture></a>
|
|
13
|
+
<a href="https://github.com/muhittincamdali/sdkbump/blob/main/package.json"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-language-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-language-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-language-light.svg" alt="言語バージョン: Node.js 22.12+"></picture></a>
|
|
14
|
+
<a href="https://github.com/muhittincamdali/sdkbump/blob/main/LICENSE"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-license-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-license-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/badge-license-light.svg" alt="ライセンス: MIT"></picture></a>
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
<p align="center">
|
|
18
|
+
<a href="#クイックスタート"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-start-ja-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-start-ja-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-start-ja-light.svg" alt="はじめる"></picture></a>
|
|
19
|
+
<a href="https://muhittincamdali.github.io/sdkbump/"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-docs-ja-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-docs-ja-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-docs-ja-light.svg" alt="ドキュメント"></picture></a>
|
|
20
|
+
<a href="https://github.com/muhittincamdali/sdkbump/tree/main/docs/guides"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-guides-ja-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-guides-ja-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-guides-ja-light.svg" alt="ガイド"></picture></a>
|
|
21
|
+
<a href="https://github.com/muhittincamdali/sdkbump/tree/main/examples"><picture><source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-examples-ja-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-examples-ja-light.svg"><img src="https://raw.githubusercontent.com/muhittincamdali/sdkbump/main/.github/brand/button-examples-ja-light.svg" alt="サンプル"></picture></a>
|
|
22
|
+
</p>
|
|
23
|
+
|
|
24
|
+
> このドキュメントは英語版 README の翻訳です。内容が異なる場合は英語版が最新です。
|
|
25
|
+
|
|
26
|
+
<!-- brand:end -->
|
|
27
|
+
|
|
28
|
+
Xcode 27 でビルドしたものをリリースする前に: sdkbump は、ネイティブ iOS、Flutter、React Native/Expo のプロジェクトを調べ、iOS 27 SDK による変更点(まず UIScene ライフサイクル)に該当する箇所を見つけて、それぞれにどの修正が当てはまるかを伝えます。プロジェクトのファイルを読むだけで、ビルドも実行も変更も行いません。
|
|
29
|
+
|
|
30
|
+
<picture><source media="(prefers-color-scheme: dark)" srcset="docs/media/demo-rn-087-dark.svg"><source media="(prefers-color-scheme: light)" srcset="docs/media/demo-rn-087-light.svg"><img src="docs/media/demo-rn-087-light.svg" alt="React Native 0.87 アプリで実行した sdkbump: iOS 27 SDK でビルドすると起動に失敗する。SCN001 はシーン構成なし、SCN002 は app delegate でのウィンドウ作成で、修正方法は 3 通り"></picture>
|
|
31
|
+
|
|
32
|
+
<sub>実際の CLI から録画したものです。対象は <a href="fixtures/rn-087">rn-087 fixture</a>、つまり <code>@react-native-community/cli init</code> で作成した React Native 0.87.1 のアプリです(<code>npm run demo</code>)。</sub>
|
|
33
|
+
|
|
34
|
+
## 主な特長
|
|
35
|
+
|
|
36
|
+
- **「起動するか」に答えます。** シーンを宣言していないアプリは Xcode 27 でビルドできますが、起動時に停止します。sdkbump は、テスト端末で気づく前にそれを伝え、変更すべきファイルを示します。
|
|
37
|
+
- **ネイティブ、Flutter、React Native、Expo** を、同じルール ID で 1 つのレポートにまとめます。出力はテキスト、Markdown、JSON から選べ、CI 向けの終了コードもあります。
|
|
38
|
+
- **プロジェクトに当てはまる修正**: React Native 0.88 または手書きのシーンデリゲート、Expo SDK 57 のオプトインまたは SDK 58、Flutter の自動マイグレーションまたは手動の手順(sdkbump は Flutter のマイグレーターと同じ条件を確認します)、SwiftUI アプリなら SwiftUI の API。
|
|
39
|
+
- **気づきにくい不具合も**: アプリにシーンができると UIKit が使わなくなる app delegate のメソッドと起動オプション(リンク、Handoff、クイックアクション、フォアグラウンドとバックグラウンドの遷移)、そして正しいウィンドウを見つけられなくなるウィンドウの取得方法。
|
|
40
|
+
- **すべての記述に出典があります。** ルールはデータとして管理され([rules/ios27.json](rules/ios27.json))、それぞれが Apple、Flutter、React Native、Expo 自身のページを引用しています。出典のないルールがあるとテストが失敗します。
|
|
41
|
+
- **iOS 27 シミュレータで確認済み**: SCN001 と SCN002 の背景にある起動失敗と黒い画面を Xcode 27.0 で再現しました。録画はリポジトリに入っています。
|
|
42
|
+
|
|
43
|
+
## クイックスタート
|
|
44
|
+
|
|
45
|
+
[Node.js](https://nodejs.org/) 22.12 以降が必要です(`node --version` で確認できます。Mac では `brew install node` でインストールできます)。ほかに必要なものはありません。
|
|
46
|
+
|
|
47
|
+
**1. アプリのフォルダでターミナルを開きます。** `.xcodeproj`、`pubspec.yaml`、`package.json` のいずれかがあるフォルダです。
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
cd path/to/YourApp
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**2. sdkbump を実行します。**
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
npx @mcamdali/sdkbump
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
npm パッケージ名は `@mcamdali/sdkbump` で、インストールされるコマンドは `sdkbump` です。スコープなしの `npx sdkbump` ではこのパッケージは実行されません。
|
|
60
|
+
|
|
61
|
+
**3. プロジェクト名の下の最初の行を読みます。** 「Fails to launch when built with the iOS 27 SDK」(iOS 27 SDK でビルドすると起動に失敗する)とある場合、**ERROR** の指摘を直すまでアプリは起動時に停止します。それぞれの指摘には、「How to fix」の一覧のどの修正が当てはまるかが書かれています。**WARNING** の指摘は起動を妨げませんが、アプリにシーンができると動作しなくなります。 「Launch not determined」(起動するかどうか判定できない)は、sdkbump が Info.plist を読めなかったことを意味します。どのファイルをなぜ読めなかったかは、レポート末尾の注記に書かれています(下の「制限事項」を参照)。
|
|
62
|
+
|
|
63
|
+
## iOS 27 SDK でビルドすると何が変わるか
|
|
64
|
+
|
|
65
|
+
Apple の [Transitioning to the UIKit scene-based life cycle](https://developer.apple.com/documentation/uikit/transitioning-to-the-uikit-scene-based-life-cycle) からの引用です(翻訳)。
|
|
66
|
+
|
|
67
|
+
> iOS 27、iPadOS 27、Mac Catalyst 27、tvOS 27、visionOS 27 以降、最新の SDK でビルドしたアプリはシーンベースのライフサイクルを採用する必要があり、採用していないと起動に失敗します。
|
|
68
|
+
|
|
69
|
+
1. **アプリがシーンを宣言していないと、起動時に停止します。** Info.plist に構成を持つ `UIApplicationSceneManifest` がなく、`application(_:configurationForConnecting:options:)` もない場合、UIKit は "UIScene life cycle is required for apps built with this SDK" というメッセージでプロセスを終了します。チェックはアプリの起動時に行われるため、コンパイラは警告を出しません。React Native 0.87 以前、オプトインしていない Expo SDK 57、Expo SDK 56 以前はこのようなアプリを作ります。Flutter ツールが移行できない Flutter アプリも同様です。
|
|
70
|
+
2. **シーンがあると、app delegate は UI イベントを受け取らなくなります。** リンク、ユーザーアクティビティ、クイックアクション、アクティブ/バックグラウンドの遷移はシーンデリゲートに渡され、app delegate が作ったウィンドウは表示されません。
|
|
71
|
+
|
|
72
|
+
[コンパイルできるのにクラッシュする理由](docs/guides/why-it-crashes.md)では、iOS 27.0 シミュレータで実行した[起動マトリクス](examples/launch-matrix/README.md)を紹介しています。
|
|
73
|
+
|
|
74
|
+
## sdkbump が調べること
|
|
75
|
+
|
|
76
|
+
| ルール | 重大度 | 指摘 | iOS 27.0 シミュレータでの結果 |
|
|
77
|
+
| ------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
|
|
78
|
+
| SCN001 | error | シーン構成がない: 構成済みの `UIApplicationSceneManifest` も `configurationForConnecting` もなく、SwiftUI の `App` でもない。`ios/` のない Expo では、SDK バージョンと `enableSceneSupport` を確認 | 起動時に停止 |
|
|
79
|
+
| SCN002 | error | app delegate が `UIWindow(frame:)` でウィンドウを作成している | アプリにシーンができると黒い画面になる |
|
|
80
|
+
| SCN003 | warning | シーンがあると UIKit が使わなくなる app delegate のメソッドと起動オプションのキー(13 個)。ただしシーンデリゲートがすでに処理している場合を除く | SwiftUI アプリで `applicationDidEnterBackground(_:)` が呼ばれない |
|
|
81
|
+
| SCN004 | warning | `UIApplication.shared.keyWindow`、`.windows`、または app delegate の `window` によるウィンドウの取得 | コンパイラの非推奨警告のみ |
|
|
82
|
+
|
|
83
|
+
ルールデータは `ios27@2026.10.15` で、Xcode 27.0(27A266a)に対して確認しています。React Native または Expo に `react-native-uiscene-bridge` や `react-native-xcode27` がインストールされている場合、それらが実行時に処理する指摘は、その README に書かれた制限とともに「処理済み」と表示され、実行の失敗にはなりません。
|
|
84
|
+
|
|
85
|
+
## インストール
|
|
86
|
+
|
|
87
|
+
npm から `sdkbump` コマンドをインストールします(パッケージ `@mcamdali/sdkbump`)。
|
|
88
|
+
|
|
89
|
+
```sh
|
|
90
|
+
npm i -g @mcamdali/sdkbump
|
|
91
|
+
sdkbump
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
プロジェクトでは `npm install --save-dev @mcamdali/sdkbump` でバージョンを固定でき、その後は `npx sdkbump` でそのコピーが実行されます。各 [GitHub リリース](https://github.com/muhittincamdali/sdkbump/releases) には同じパッケージが `sdkbump-<バージョン>.tgz` として `SHA256SUMS` ファイルと一緒に含まれており、`npx` で URL から npm を介さずに実行できます。`muhittincamdali/tap` 向けの Homebrew formula はリリースワークフローが用意します(tap の最初のリリースと合わせて予定しています)。
|
|
95
|
+
|
|
96
|
+
## 使い方
|
|
97
|
+
|
|
98
|
+
```text
|
|
99
|
+
sdkbump [path] [options]
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
| オプション | 内容 |
|
|
103
|
+
| ----------------------- | --------------------------------------------------------------------------- |
|
|
104
|
+
| `path` | プロジェクトのフォルダまたは `.xcodeproj`。デフォルトはカレントフォルダ |
|
|
105
|
+
| `-f, --format <format>` | `tty`(デフォルト)、`markdown`、`json` |
|
|
106
|
+
| `-o, --output <file>` | レポートをターミナルではなくファイルに書き出す |
|
|
107
|
+
| `--fail-on <severity>` | `error`(デフォルト)、`warning`、`info`、`none`: 終了コードが 1 になる条件 |
|
|
108
|
+
| `--no-color` | ターミナルでもプレーンテキストにする(`NO_COLOR` と `FORCE_COLOR` に対応) |
|
|
109
|
+
|
|
110
|
+
終了コード: `0` は `--fail-on` 以上で未処理の指摘がないこと、`1` はそれ以上の指摘があること、`2` は引数の誤り、iOS プロジェクトが見つからない、または予期しないエラーです。
|
|
111
|
+
|
|
112
|
+
sdkbump は iOS アプリを自動で見つけます。ネイティブアプリではルートまたは 1 階層下の `.xcodeproj`、Flutter、React Native、Expo のアプリでは `ios/`(Flutter プラグインでは `example/ios/`)です。プロジェクトファイルにあるすべての iOS アプリターゲット、それぞれが指す Info.plist(XML またはバイナリ)、アプリの Swift と Objective-C のファイルを読み、Pods、`node_modules`、ビルド成果物、テストは除外します。`ios/` のない Expo アプリは package.json と app.json から調べます。
|
|
113
|
+
|
|
114
|
+
### Markdown のレポートをコードと一緒に保存する
|
|
115
|
+
|
|
116
|
+
```sh
|
|
117
|
+
npx @mcamdali/sdkbump --format markdown --output sdkbump.md
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### JSON のレポートをスクリプトで使う
|
|
121
|
+
|
|
122
|
+
```sh
|
|
123
|
+
npx @mcamdali/sdkbump --format json > sdkbump.json
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
各指摘には、`rule`、`severity`、`file`、`line`、`message`、手順とガイドを含む `fix`、`alternatives`、`mitigation`(回避策のパッケージが処理する場合に設定されます)、`sources` があります。構造は `schemaVersion` 0 で、1.0 より前に変わる可能性があります。[examples/shell/launch-blockers.sh](examples/shell/launch-blockers.sh) は `jq` で絞り込む例です。
|
|
127
|
+
|
|
128
|
+
### CI で実行する
|
|
129
|
+
|
|
130
|
+
[examples/github-actions/sdkbump.yml](examples/github-actions/sdkbump.yml) は、iOS アプリに変更を加えるすべての pull request のジョブサマリーにレポートを追加し、error があればジョブを失敗させます。
|
|
131
|
+
|
|
132
|
+
### JavaScript から使う
|
|
133
|
+
|
|
134
|
+
```js
|
|
135
|
+
import { render, scan } from 'sdkbump';
|
|
136
|
+
|
|
137
|
+
const report = await scan('path/to/app');
|
|
138
|
+
console.log(report.verdict.text);
|
|
139
|
+
console.log(render(report, 'markdown'));
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
実行できるサンプルは [examples/api/verdicts.mjs](examples/api/verdicts.mjs) です。
|
|
143
|
+
|
|
144
|
+
## デモ
|
|
145
|
+
|
|
146
|
+
ターミナルの録画は、各ツールチェーンで作成した実際のプロジェクトである [fixtures](fixtures/README.md) に対して CLI を実行したものです。
|
|
147
|
+
|
|
148
|
+
| プロジェクト | 録画 |
|
|
149
|
+
| ------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
|
|
150
|
+
| React Native 0.87.1 のアプリ | このページの先頭 |
|
|
151
|
+
| AppDelegate をカスタマイズした Flutter アプリ(Flutter 3.24) | [ライト](docs/media/demo-flutter-light.svg) · [ダーク](docs/media/demo-flutter-dark.svg) |
|
|
152
|
+
| アダプター方式の app delegate を使う SwiftUI アプリ | [ライト](docs/media/demo-swiftui-light.svg) · [ダーク](docs/media/demo-swiftui-dark.svg) |
|
|
153
|
+
|
|
154
|
+
iOS 27.0 シミュレータ(iPhone 17、Xcode 27.0 でビルド)では、ネイティブ UIKit の fixture は起動時に停止し、同じアプリをシーンデリゲートに移行すると起動します。
|
|
155
|
+
|
|
156
|
+
<picture><source media="(prefers-color-scheme: dark)" srcset="docs/media/demo-simulator-native-uikit-dark.svg"><source media="(prefers-color-scheme: light)" srcset="docs/media/demo-simulator-native-uikit-light.svg"><img src="docs/media/demo-simulator-native-uikit-light.svg" alt="iOS 27.0 シミュレータでの scripts/simulator-check.sh native-uikit: 起動の 4 秒後に動作しておらず、UIKit の出力は Application failed to launch: UIScene life cycle is required for apps built with this SDK"></picture>
|
|
157
|
+
|
|
158
|
+
<p align="center"><img src="docs/media/simulator/launched.png" width="480" alt="Xcode 27.0 でビルドした native-uikit-scenes と native-swiftui の fixture が、iOS 27.0 の iPhone 17 シミュレータで動作している様子"></p>
|
|
159
|
+
|
|
160
|
+
2026 年 10 月 15 日に、Node.js 26.11 を使った Mac(Apple silicon、M5 Max)で、ほかのジョブが動いている状態で計測しました。10 件の fixture に対する `node dist/cli/main.js` の実行 100 回を 1 セットとして 3 セット行い、Node.js の起動時間を含めた中央値は各セットで 0.11 秒、0.12 秒、0.19 秒、最も遅い実行は 0.33 秒でした。マシンの負荷が高いほど時間は長くなります。
|
|
161
|
+
|
|
162
|
+
## ステータス
|
|
163
|
+
|
|
164
|
+
| 機能 | ステータス |
|
|
165
|
+
| -------------------------------------------------------------------------------------------------- | ----------- |
|
|
166
|
+
| ネイティブ、Flutter(アプリとプラグインのサンプル)、React Native、Expo のプロジェクト検出 | 動作します |
|
|
167
|
+
| アプリ自身の Info.plist と Swift/Objective-C ソースに対する SCN001 から SCN004 | 動作します |
|
|
168
|
+
| エコシステムとバージョンに応じた修正の選択、Flutter 自動マイグレーションの確認、回避策のパッケージ | 動作します |
|
|
169
|
+
| ターミナル、Markdown、JSON のレポート、`--fail-on` の終了コード | 動作します |
|
|
170
|
+
| 依存関係: Pods、`node_modules`、Flutter プラグインのソース(パッケージ名つき) | 予定(0.2) |
|
|
171
|
+
| 回避策の通知を独立した SCN005 ルールとして提供、15.0 未満のデプロイメントターゲットの DPT001 | 予定(0.2) |
|
|
172
|
+
| `--verify`: CLI から iOS 27 シミュレータでビルドして起動 | 予定(0.3) |
|
|
173
|
+
| パターンではなく Swift/Objective-C の構文木、ビルド済み `.app` のチェック、SiriKit の非推奨 | 予定(0.5) |
|
|
174
|
+
| ネイティブアプリ向けの `fix --dry-run`、SARIF 出力、GitHub Action | 予定(0.8) |
|
|
175
|
+
| 安定したルールスキーマと JSON 構造 | 予定(1.0) |
|
|
176
|
+
|
|
177
|
+
## 制限事項
|
|
178
|
+
|
|
179
|
+
- **コンパイラではなくパターンです。** ルールは、コメントと文字列を空白に置き換えた Swift と Objective-C のテキストに対する正規表現です。生成されたコード、マクロの中のコード、変わった書き方のコードは、見落としたり誤って検出したりすることがあります。構文木への移行は予定(0.5)です。
|
|
180
|
+
- **アプリ自身のソースだけを読みます。** Pods、`node_modules`、Flutter プラグインなどの依存関係は読まないため、UIKit がもう呼ばない app delegate のメソッドに頼るプラグインは報告されません。依存関係のチェックは予定(0.2)です。
|
|
181
|
+
- **ビルド設定は project.pbxproj からのみ読みます。** sdkbump はプロジェクトファイルから `INFOPLIST_FILE` と `GENERATE_INFOPLIST_FILE` を読み、`$(SRCROOT)`、`$(PROJECT_DIR)`、`$(TARGET_NAME)`、`$(PRODUCT_NAME)` を展開します。`.xcconfig` ファイルは読まず、ほかのビルド設定も展開せず、プロジェクトフォルダの外にある Info.plist も読みません。ターゲットの Info.plist を読めないときは、推測する代わりに SCN001 を info の指摘とし、判定を「Launch not determined」にします。
|
|
182
|
+
- **抑制ファイルはありません。** 指摘を確認済みとして印を付けることはできません。どの重大度で実行を失敗にするかは `--fail-on` で決めます。
|
|
183
|
+
- **ファイルを読むだけです。** sdkbump はアプリをビルドも起動もしません。`--verify` は予定(0.3)です。
|
|
184
|
+
|
|
185
|
+
## ドキュメント
|
|
186
|
+
|
|
187
|
+
API リファレンスとガイド: [muhittincamdali.github.io/sdkbump](https://muhittincamdali.github.io/sdkbump/)。
|
|
188
|
+
|
|
189
|
+
## ガイド
|
|
190
|
+
|
|
191
|
+
- [コンパイルできるのにクラッシュする理由](docs/guides/why-it-crashes.md)
|
|
192
|
+
- [ネイティブの UIKit と SwiftUI のアプリ](docs/guides/native-ios.md)
|
|
193
|
+
- [Flutter: カスタム AppDelegate とプラグイン](docs/guides/flutter.md)
|
|
194
|
+
- [0.88 より前の React Native と SDK 58 より前の Expo](docs/guides/react-native-expo.md)
|
|
195
|
+
- [ネイティブモジュールの作者向け: コールドスタート時のリンクと通知](docs/guides/native-module-authors.md)
|
|
196
|
+
|
|
197
|
+
## 関連ツール
|
|
198
|
+
|
|
199
|
+
同じ変更に取り組んでいるプロジェクトは、ほかにもあります。どれが合うかは、必要なものによって変わります。
|
|
200
|
+
|
|
201
|
+
- [react-native-uiscene-bridge](https://github.com/Atomics-hub/react-native-uiscene-bridge) と [react-native-xcode27](https://github.com/Atomics-hub/react-native-xcode27) は、コードを変更せずに、実行時に React Native または Expo のアプリを起動できるようにします。まだアップグレードできない場合に向いています。sdkbump はこれらを認識します。
|
|
202
|
+
- [auditor-uiscene](https://github.com/Anzell/auditor-uiscene) は、シェルスクリプトで Flutter アプリとそのプラグインを監査します。
|
|
203
|
+
- Flutter 自身のマイグレーター(3.41 以降の `flutter build ios`)は、変更を加えていない Flutter アプリを移行します。
|
|
204
|
+
- [flutter_spm_doctor](https://pub.dev/packages/flutter_spm_doctor) は Flutter プラグインをチェックします。
|
|
205
|
+
|
|
206
|
+
## 動作要件
|
|
207
|
+
|
|
208
|
+
| ツールチェーン | 最小バージョン |
|
|
209
|
+
| -------------- | -------------- |
|
|
210
|
+
| Node.js | 22.12 |
|
|
211
|
+
|
|
212
|
+
sdkbump に Xcode は不要です。ファイルを読むだけなので、Linux でも動作します。CI では Node.js 22 と 24(Linux)でテストを実行します。ローカルでは、280 件すべてが Mac(Apple silicon)上の Node.js 22.23、24.22、26.11 で成功しています。シミュレータの録画には Xcode 27 を入れた Mac が必要で、CI には含まれません。
|
|
213
|
+
|
|
214
|
+
## アーキテクチャ
|
|
215
|
+
|
|
216
|
+
```text
|
|
217
|
+
path ─► detectProject native | flutter | react-native | expo; iOS folder; versions
|
|
218
|
+
─► collectApp iOS app targets from project.pbxproj, their Info.plist (XML or binary),
|
|
219
|
+
Swift and Objective-C sources with comments and strings blanked
|
|
220
|
+
─► checkApp SCN001…SCN004, fix per ecosystem and version, workaround packages
|
|
221
|
+
rules/ios27.json what each rule says, fixes, sources (validated with zod)
|
|
222
|
+
─► render tty | markdown | json
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
- 検出パターンは、コメントと文字列を空白にしたソーステキストに対する正規表現です。必要な場面では、app delegate またはシーンデリゲートの内側にあるものだけを数えます。
|
|
226
|
+
- ルールデータはコードから分離されており、バージョン管理されています(`ios27@2026.10.15`)。ルール、修正、回避策のいずれかに出典がないと、テストが失敗します。
|
|
227
|
+
- CLI(`src/cli/`)は、引数の解析、色と幅の選択、終了コードの設定だけを行います。
|
|
228
|
+
|
|
229
|
+
## ロードマップ
|
|
230
|
+
|
|
231
|
+
[ステータス](#ステータス)の表を参照してください。0.2 で依存関係とデプロイメントターゲット、0.3 で CLI からのシミュレータ起動、0.5 で構文木とビルド済みアプリのチェック、0.8 で修正と SARIF、1.0 で安定したスキーマを追加します。各リリースの変更点は [CHANGELOG.md](CHANGELOG.md) にあります。
|
|
232
|
+
|
|
233
|
+
## FAQ
|
|
234
|
+
|
|
235
|
+
**私のアプリは今日 iOS 27 で動いています。影響はありますか?** Xcode 26 以前でビルドしたものであれば、このチェックはそのビルドには当てはまりません。今回の検証では、iOS 26 SDK にリンクした同じコードが iOS 27 シミュレータで起動しました。Xcode 27 での次回のビルドから当てはまります。
|
|
236
|
+
|
|
237
|
+
**sdkbump は実機でのテストの代わりになりますか?** いいえ。ファイルを読むだけです。このリポジトリにあるシミュレータの録画は iOS 27.0 シミュレータのもので、実機で実行したものはありません。
|
|
238
|
+
|
|
239
|
+
**なぜ指摘が「処理済み」と表示されるのですか?** package.json にある回避策のパッケージ(react-native-uiscene-bridge または react-native-xcode27)が、実行時にシーンを宣言するためです。アプリは起動しますが、アプリ自身にはまだシーンのサポートがありません。レポートには、そのパッケージの制限と本来の修正方法が載ります。
|
|
240
|
+
|
|
241
|
+
**sdkbump はプロジェクトを変更しますか?** いいえ。プロジェクトを読み、求められたレポートだけを書き出します。
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
## コントリビューション
|
|
245
|
+
|
|
246
|
+
コントリビューションを歓迎します。pull request を作成する前に[コントリビューションガイド](CONTRIBUTING.md)と[行動規範](https://github.com/muhittincamdali/.github/blob/main/CODE_OF_CONDUCT.md)をお読みください。セキュリティ上の問題は[セキュリティポリシー](SECURITY.md)に従って非公開で報告してください。
|
|
247
|
+
|
|
248
|
+
## ライセンス
|
|
249
|
+
|
|
250
|
+
MIT ライセンスで公開しています。詳細は [LICENSE](LICENSE) を参照してください。
|