captive-stack-detector 0.6.0 → 0.7.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.
- checksums.yaml +4 -4
- data/docs/stacks.md +105 -0
- data/lib/captive_stack_detector/js_stack_detector.rb +1 -0
- data/lib/captive_stack_detector/package_json_analyzer.rb +7 -0
- data/lib/captive_stack_detector/types.rb +6 -1
- data/lib/captive_stack_detector/version.rb +1 -1
- data/lib/captive_stack_detector.rb +3 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d7799cc8a4c640bb12eca8a85e86e4d4e59eaae472764cc07d255f1481d8592c
|
|
4
|
+
data.tar.gz: e9481131febb4b7d7e9558ba629941d5d19025fd548b91afe458c71c51280f41
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ba37a8e26e9356235db1f390d9d80eefae0eb585f1709f9bb1ef5d8b90ee8c2c82e50506ddebe9fa8ae3a337b096a675e48abd95d8c586130c4ed6416d8c89cf
|
|
7
|
+
data.tar.gz: cb1e564350c211cfc8bc1906857e413e099fbe368f5d5d9029a2c7074dbaf168034aa85d5924596606f9ca9d5ded9dcd617559fb95f7befe58e647eaf161078b
|
data/docs/stacks.md
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Stacks supportées
|
|
2
|
+
|
|
3
|
+
Quand vous créez une application, Captive lit votre dépôt GitHub pour savoir **comment le construire et le lancer**. Cette famille de déploiement s'appelle la **stack**. Captive en connaît trois : **Rails**, **Node** et **Expo**. Si votre dépôt n'entre dans aucune, la création est refusée avec la raison exacte.
|
|
4
|
+
|
|
5
|
+
Captive ne lit que **la racine du dépôt** : un `Gemfile` ou un `package.json` placé dans un sous-dossier n'est pas vu.
|
|
6
|
+
|
|
7
|
+
## Rails
|
|
8
|
+
|
|
9
|
+
Condition : un `Gemfile` à la racine qui contient la gem `rails`.
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
gem "rails", "8.1.0"
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
- Avec une gem d'assets (`propshaft`, `sprockets-rails`, `importmap-rails`, `jsbundling-rails`, `cssbundling-rails`, `tailwindcss-rails`…), l'application est construite avec ses assets frontend.
|
|
16
|
+
- Sans gem d'assets, elle est construite comme une API.
|
|
17
|
+
- `gem "pg"` provisionne une base Postgres, `gem "redis"` ou `gem "sidekiq"` un Redis.
|
|
18
|
+
|
|
19
|
+
Si un `Gemfile` est présent, c'est toujours lui qui décide : un dépôt avec un `Gemfile` sans Rails est refusé, même s'il a aussi un `package.json`.
|
|
20
|
+
|
|
21
|
+
## Node
|
|
22
|
+
|
|
23
|
+
Condition : un `package.json` à la racine, sans dépendance `expo`, avec un script **`start`** ou **`build`**.
|
|
24
|
+
|
|
25
|
+
### Application web (SPA : Vite, React, Vue…)
|
|
26
|
+
|
|
27
|
+
Votre application est buildée une fois, puis servie en fichiers statiques. Aucun process Node ne tourne en production.
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"scripts": {
|
|
32
|
+
"dev": "vite",
|
|
33
|
+
"build": "vite build"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"vite": "7.1.0"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
- Le script `build` doit produire le dossier **`dist/`** à la racine. C'est le comportement par défaut de Vite ; si vous avez changé `build.outDir`, remettez `dist`.
|
|
42
|
+
- Toutes les routes inconnues renvoient `index.html` : le routage côté client (React Router, Vue Router…) fonctionne sans configuration.
|
|
43
|
+
- Les variables d'environnement sont injectées **au moment du build** (par exemple `VITE_SUPABASE_URL`). Après en avoir modifié une, redéployez.
|
|
44
|
+
|
|
45
|
+
### Serveur Node (Next.js, Nuxt, SvelteKit, Remix)
|
|
46
|
+
|
|
47
|
+
Si votre `package.json` dépend de `next`, `nuxt`, `@sveltejs/kit` ou d'un paquet `@remix-run/…`, Captive lance un vrai serveur Node avec votre script `start`.
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"scripts": {
|
|
52
|
+
"build": "next build",
|
|
53
|
+
"start": "next start"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"next": "15.0.0"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Services
|
|
62
|
+
|
|
63
|
+
- `pg` ou `postgres` provisionne une base Postgres.
|
|
64
|
+
- `redis` ou `ioredis` provisionne un Redis.
|
|
65
|
+
- `@supabase/supabase-js` ou `@supabase/ssr` provisionne un backend Supabase.
|
|
66
|
+
- Une ligne `worker: <commande>` dans un `Procfile` lance un worker.
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
### Variables exposées au navigateur
|
|
70
|
+
|
|
71
|
+
Une variable n'arrive dans le code du navigateur que si elle porte le préfixe de votre bundler. Captive le déduit de vos dépendances :
|
|
72
|
+
|
|
73
|
+
| Dépendance | Préfixe |
|
|
74
|
+
| --- | --- |
|
|
75
|
+
| `expo` | `EXPO_PUBLIC_` |
|
|
76
|
+
| `next` | `NEXT_PUBLIC_` |
|
|
77
|
+
| `vite` | `VITE_` |
|
|
78
|
+
|
|
79
|
+
Si plusieurs sont présentes, c'est le premier de la liste qui l'emporte (`vite` est souvent là pour les tests seulement).
|
|
80
|
+
|
|
81
|
+
Avec un backend Supabase, Captive pose l'URL et la clé publique sous ce préfixe, avec les deux noms de clé en usage : `VITE_SUPABASE_URL`, `VITE_SUPABASE_ANON_KEY` et `VITE_SUPABASE_PUBLISHABLE_KEY` pour une application Vite, par exemple. Côté serveur, les mêmes valeurs sont disponibles sans préfixe : `SUPABASE_URL` et `SUPABASE_ANON_KEY`.
|
|
82
|
+
|
|
83
|
+
Ces variables sont lues **au build** : après en avoir changé une, redéployez.
|
|
84
|
+
|
|
85
|
+
## Expo
|
|
86
|
+
|
|
87
|
+
Condition : un `package.json` à la racine avec la dépendance `expo` (dans `dependencies` ou `devDependencies`). Aucun script n'est exigé.
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"dependencies": {
|
|
92
|
+
"expo": "54.0.0"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Ma création est refusée
|
|
98
|
+
|
|
99
|
+
| Message | Cause | Que faire |
|
|
100
|
+
| --- | --- | --- |
|
|
101
|
+
| Aucun Gemfile ni package.json à la racine du dépôt. | Pas de fichier de dépendances à la racine. | Vérifiez que l'application est bien à la racine du dépôt, pas dans un sous-dossier (`app/`, `frontend/`…). Les monorepos ne sont pas pris en charge. |
|
|
102
|
+
| Gemfile trouvé, mais sans la gem rails. | Application Ruby non Rails (Sinatra, Hanami…), ou `Gemfile` d'outillage dans un projet JavaScript. | Seul Rails est pris en charge côté Ruby. Si le `Gemfile` ne sert qu'à de l'outillage, retirez-le du dépôt. |
|
|
103
|
+
| package.json trouvé, mais sans dépendance expo ni script start ou build. | Captive ne sait pas comment construire l'application. | Ajoutez un script `build` (application web) ou `start` (serveur), comme dans les exemples ci-dessus. |
|
|
104
|
+
|
|
105
|
+
Si votre stack n'est pas listée ici, contactez l'équipe Captive.
|
|
@@ -5,6 +5,7 @@ require_relative "ssr_framework_detector"
|
|
|
5
5
|
|
|
6
6
|
module CaptiveStackDetector
|
|
7
7
|
class PackageJsonAnalyzer
|
|
8
|
+
PUBLIC_ENV_PREFIXES = { "expo" => "EXPO_PUBLIC_", "next" => "NEXT_PUBLIC_", "vite" => "VITE_" }.freeze
|
|
8
9
|
# Des clients, pas des ORM : Prisma ou Drizzle parlent aussi MySQL et SQLite, leur
|
|
9
10
|
# présence ne dit pas que l'app attend une base Postgres.
|
|
10
11
|
POSTGRES_CLIENTS = %w[pg postgres].freeze
|
|
@@ -41,6 +42,12 @@ module CaptiveStackDetector
|
|
|
41
42
|
any_dep?(SUPABASE_CLIENTS) ? "supabase" : nil
|
|
42
43
|
end
|
|
43
44
|
|
|
45
|
+
# Le premier bundler trouvé, dans l'ordre du type : vite en dernier, parce qu'il arrive
|
|
46
|
+
# souvent avec Vitest sans construire le front.
|
|
47
|
+
def public_env_prefix
|
|
48
|
+
PUBLIC_ENV_PREFIXES.find { |dependance, _| deps.key?(dependance) }&.last
|
|
49
|
+
end
|
|
50
|
+
|
|
44
51
|
private
|
|
45
52
|
|
|
46
53
|
def any_dep?(names)
|
|
@@ -4,7 +4,12 @@ module CaptiveStackDetector
|
|
|
4
4
|
Services = Data.define(:database, :queue, :backend)
|
|
5
5
|
Worker = Data.define(:command)
|
|
6
6
|
Runtime = Data.define(:ruby, :node)
|
|
7
|
-
|
|
7
|
+
# public_env_prefix : préfixe des variables que le bundler expose au navigateur
|
|
8
|
+
# (VITE_, NEXT_PUBLIC_, EXPO_PUBLIC_), nil sans bundler front (PackageJsonAnalyzer).
|
|
9
|
+
Result = Data.define(:type, :subtype, :services, :worker, :runtime, :env_vars, :system_packages,
|
|
10
|
+
:public_env_prefix) do
|
|
11
|
+
def initialize(public_env_prefix: nil, **) = super
|
|
12
|
+
end
|
|
8
13
|
|
|
9
14
|
# reason : :no_manifest, :no_rails ou :no_node_entry, pour que l'appelant explique le refus.
|
|
10
15
|
class UnsupportedStack < StandardError
|
|
@@ -8,6 +8,9 @@ require_relative "captive_stack_detector/rails_stack_detector"
|
|
|
8
8
|
require_relative "captive_stack_detector/js_stack_detector"
|
|
9
9
|
|
|
10
10
|
module CaptiveStackDetector
|
|
11
|
+
# Doc publique des stacks supportées, livrée dans la gem et affichée par le dashboard (ADR 0003).
|
|
12
|
+
DOC_PATH = File.expand_path("../docs/stacks.md", __dir__)
|
|
13
|
+
|
|
11
14
|
def self.detect(local_path: nil, github_token: nil, repo: nil)
|
|
12
15
|
reader = FileReader.build(local_path: local_path, github_token: github_token, repo: repo)
|
|
13
16
|
detect_from(reader)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: captive-stack-detector
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Captive Studio
|
|
@@ -17,6 +17,7 @@ executables: []
|
|
|
17
17
|
extensions: []
|
|
18
18
|
extra_rdoc_files: []
|
|
19
19
|
files:
|
|
20
|
+
- docs/stacks.md
|
|
20
21
|
- lib/captive/stack/detector.rb
|
|
21
22
|
- lib/captive_stack_detector.rb
|
|
22
23
|
- lib/captive_stack_detector/aptfile_parser.rb
|