wslc-wip 0.14.1 → 0.15.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 103045e33c74bb6772808c9a2e3029d35c90ce190c520df0ecc6d2a803b6108b
4
- data.tar.gz: c70c47ae4c0d45a3ec0f9d695e4359d1d8915e5716b546c52d53280c1e49d09a
3
+ metadata.gz: b8248f18abf8e946e333de3e2e9b70e72b9b0f8806a3216c97e62bfe83ad53bb
4
+ data.tar.gz: 19119fe6787aad4b17cc6ed9e1f1048d664cbcd119414bd4bc4b86e0c26dfb5d
5
5
  SHA512:
6
- metadata.gz: b51cdbdfe08a7d51ef750a8a5190583c9f3de894bf5e419b5890a6cdbfda4c9da1a1ab6fb175b763669100564e2e1741ff4bfc1dbf2819e46358680515e5fafb
7
- data.tar.gz: 91b3608c4666a2e1023b3ce9e7069fe29d3fc8ecfa03cf0641e5e6da8d487b89b4fed13b3d948040e8b65b4d5e4828ac361b1be96ce8be470dbca8be58f58e5c
6
+ metadata.gz: 91535a4b496bc4cc2e55cc44d7feadbf8709811df0ab660c7d7fe8e6f20feccac18a497804b13bd83a6d2775396e3061c51f64040864e3d6635eeaf22edf9b8e
7
+ data.tar.gz: 1151d286900c2c11812c607f123d966862ea41b1ac5ee01a74d957f0626667c616fdabf13f618fdad4a62a1b4c8a26f1c68bf837030f1e8f4508a8f2d0e733b1
data/README.md CHANGED
@@ -181,6 +181,17 @@ sync:
181
181
  tag: null # optional (default: "wip-sync-<container>:latest")
182
182
  ```
183
183
 
184
+ `wip init --template NAME` writes `exclude`'s default list live, picked from that stack's own
185
+ `github/gitignore` template:
186
+
187
+ | `--template` | Stack | Default `exclude` |
188
+ |---|---|---|
189
+ | `rails` | Rails | `.git`, `log/`, `tmp/`, `storage/`, `public/assets/`, `public/packs/`, `.bundle/`, `vendor/bundle/`, `coverage/`, `node_modules/` |
190
+ | `node` | Node.js | `.git`, `node_modules/`, `dist/`, `build/`, `.next/`, `.cache/`, `coverage/` |
191
+ | `rust` | Rust | `.git`, `target/` |
192
+ | `csharp` | C# | `.git`, `bin/`, `obj/`, `.vs/`, `packages/` |
193
+ | (omitted) | — | `.git`, `tmp/`, `node_modules/` |
194
+
184
195
  Everything below `sync:` is optional — `sync: {}` alone already works. With it in place:
185
196
 
186
197
  - Any `volumes` entry on the primary container mounting `target` (the usual `.:/app`) is replaced
@@ -341,7 +352,7 @@ valid compose.yml over sections it doesn't need to look at:
341
352
 
342
353
  | Command | Description |
343
354
  |---|---|
344
- | `wip init [--force]` | Write a starter `wip.yml`: `mode: compose-native` if a `compose.yml`/`docker-compose.yml` is found next to it, `mode: container` otherwise. Refuses to overwrite an existing `wip.yml` unless `--force` |
355
+ | `wip init [--force] [--template NAME]` | Write a starter `wip.yml`: `mode: compose-native` if a `compose.yml`/`docker-compose.yml` is found next to it, `mode: container` otherwise. `--template` picks `sync.exclude`'s default patterns for a stack (`rails`, `node`, `rust`, `csharp`); omitted, it falls back to `.git`/`tmp/`/`node_modules/`. Refuses to overwrite an existing `wip.yml` unless `--force` |
345
356
  | `wip version` | wip's version, plus WSLC's if it can be detected |
346
357
  | `wip doctor` | Diagnose WSL2, interop, WSLC, config, architecture, and Git |
347
358
  | `wip config` | Print the effective configuration (secrets masked) |
data/lib/wip/cli.rb CHANGED
@@ -42,11 +42,13 @@ module Wip
42
42
 
43
43
  desc 'init', 'Create a starter wip.yml (detects an existing compose.yml/docker-compose.yml)'
44
44
  option :force, type: :boolean, default: false, desc: 'Overwrite an existing wip.yml'
45
+ option :template, type: :string,
46
+ desc: "sync.exclude preset: #{Initializer::TEMPLATE_LABELS.keys.join(', ')} (default: none)"
45
47
  def init
46
48
  path = Pathname(options[:config] || ConfigLoader::FILENAME).expand_path
47
49
  raise Error, "#{path} already exists (use --force to overwrite)" if path.file? && !options[:force]
48
50
 
49
- initializer = Initializer.new(dir: path.dirname)
51
+ initializer = Initializer.new(dir: path.dirname, template: options[:template])
50
52
  path.write(initializer.call)
51
53
  warn "wip: wrote #{path} (mode: #{initializer.compose? ? 'compose-native' : 'container'})"
52
54
  end
@@ -1,68 +1,61 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'pathname'
4
+
3
5
  module Wip
4
6
  # Builds a starter wip.yml. Detects an existing compose file next to the
5
7
  # target (the same filenames ComposeBridge auto-detects) to decide between
6
8
  # mode: compose-native and mode: container, since that's the one decision
7
9
  # `wip init` can't leave to a placeholder.
8
10
  class Initializer
9
- # Shared across both templates: every sync.* key SyncSettings understands,
10
- # commented out with its default/behavior so nothing has to be looked up
11
- # in the README to customize the mirror.
12
- SYNC_TEMPLATE = <<~YAML.chomp
13
- sync: {} # optional; mirrors the source into a named volume instead of bind-mounting it live
14
- # source: . # optional; host path to mirror (default: wip.yml directory)
15
- # target: /app # optional; in-container path the mirror volume mounts at (default: workdir, else /app)
16
- # mount: /host-src # optional; read-only host mount inside the container (default: /host-src)
17
- # volume: app-src # optional; named volume that holds the mirrored tree (default: "<container>-src")
18
- # delete: true # optional; rsync --delete so removals on the host are mirrored too (default: true)
19
- # exclude: [] # optional; rsync --exclude patterns, e.g. ["node_modules", "*.log"]
20
- # command: rsync # optional; mirror binary to shell out to (default: rsync)
21
- # options: [] # optional; extra flags appended to the mirror command
22
- # interval: 2 # optional; seconds between mirrors (default: 2)
23
- # mode: exec # optional; exec (default, mirrors into the running container) | run (fresh container each mirror)
24
- # image: # optional; image the mirror container runs (required under mode: compose unless build: is set)
25
- # build: # optional; let wip build a small dedicated mirror image instead of requiring one to exist
26
- # dockerfile: # TODO required if build: is set
27
- # tag: # optional (default: wip-sync-<container>:latest)
28
- YAML
29
-
30
- CONTAINER_TEMPLATE = <<~YAML.freeze
31
- version: 1
32
- mode: container # container | compose | compose-native (see README)
33
- container: app # TODO: rename freely, as long as it matches a key under dependencies: below
34
-
35
- # wslc: {} # optional; override which wslc binary/path wip shells out to (default: auto)
36
- # command: auto
37
-
38
- # network: my-network # optional; container network name (mode: container only)
39
-
40
- dependencies:
41
- app: # this is the container wip creates, execs into, and runs commands in
42
- image: your/image:tag # TODO: image to run
43
- workdir: /app # TODO: adjust to match your image, or delete this line
44
- # interactive: false # optional; keep stdin open / allocate a tty (default: false)
45
- # remove: true # optional; remove the container after each run (default: true)
46
- # env: {} # optional; environment variables passed to the container, e.g. {FOO: bar}
47
- # ports: [] # optional; published ports, e.g. ["3000:3000"]
48
- # volumes: [] # optional; extra -v specs beyond the source/sync mounts
49
-
11
+ # --template values wip init accepts, and the label used in the exclude: comment.
12
+ TEMPLATE_LABELS = {
13
+ 'rails' => 'Rails',
14
+ 'node' => 'Node.js',
15
+ 'rust' => 'Rust',
16
+ 'csharp' => 'C#'
17
+ }.freeze
18
+
19
+ # sync.exclude patterns written live for each --template. They mirror that
20
+ # stack's own github/gitignore template — directories that are either
21
+ # regenerated inside the container or too large/irrelevant to mirror over rsync.
22
+ TEMPLATE_EXCLUDES = {
23
+ 'rails' => %w[.git log/ tmp/ storage/ public/assets/ public/packs/ .bundle/ vendor/bundle/
24
+ coverage/ node_modules/],
25
+ 'node' => %w[.git node_modules/ dist/ build/ .next/ .cache/ coverage/],
26
+ 'rust' => %w[.git target/],
27
+ 'csharp' => %w[.git bin/ obj/ .vs/ packages/]
28
+ }.freeze
29
+
30
+ # Used when --template is omitted — the same starting point the README's own
31
+ # example uses.
32
+ FALLBACK_EXCLUDES = %w[.git tmp/ node_modules/].freeze
33
+
34
+ # Appended to both templates after dependencies/compose. commands: itself is left
35
+ # commented since an empty commands: {} is indistinguishable from omitting the key.
36
+ COMMANDS_EXAMPLE = <<~YAML.chomp
37
+ # optional; custom subcommands, e.g. `wip test` — see README
50
38
  # commands:
51
- # test: # example custom command, invoked as `wip test`
52
- # type: exec # optional; exec (default, runs in the running container) | run (fresh container) | build
53
- # command: bundle exec rspec # TODO
39
+ # test:
40
+ # optional; exec (default, runs in the running container) | run (fresh container) | build
41
+ # type: exec
54
42
 
55
- #{SYNC_TEMPLATE}
43
+ # TODO
44
+ # command: bundle exec rspec
56
45
  YAML
57
46
 
58
- def initialize(dir: Dir.pwd)
47
+ def initialize(dir: Dir.pwd, template: nil)
48
+ raise Error, "unknown --template #{template.inspect} (valid: #{TEMPLATE_LABELS.keys.join(', ')})" \
49
+ if template && !TEMPLATE_LABELS.key?(template)
50
+
59
51
  @dir = dir
52
+ @template = template
60
53
  end
61
54
 
62
55
  def compose? = !!compose_file
63
56
 
64
57
  def call
65
- compose? ? compose_template : CONTAINER_TEMPLATE
58
+ compose? ? compose_template : container_template
66
59
  end
67
60
 
68
61
  private
@@ -71,28 +64,161 @@ module Wip
71
64
  @compose_file ||= ComposeBridge::FILENAMES.find { |name| File.file?(File.join(@dir, name)) }
72
65
  end
73
66
 
67
+ # Directory name wip.yml would resolve as its default compose.project (and, from
68
+ # that, its network name) if left unset — shown as a comment so it's discoverable
69
+ # without duplicating it as a live value that would go stale if the directory moves.
70
+ def compose_project_default = Pathname(@dir).basename.to_s
71
+
72
+ def exclude_comment
73
+ if @template
74
+ "# optional; rsync --exclude patterns picked for --template #{@template} (#{TEMPLATE_LABELS[@template]})"
75
+ else
76
+ '# optional; rsync --exclude patterns, e.g. ["node_modules", "*.log"]'
77
+ end
78
+ end
79
+
80
+ def exclude_list
81
+ patterns = @template ? TEMPLATE_EXCLUDES.fetch(@template) : FALLBACK_EXCLUDES
82
+ patterns.map { |pattern| " - #{pattern}" }.join("\n")
83
+ end
84
+
85
+ # Appended to sync: in both templates. Every key here is either a plain constant
86
+ # default (safe to state literally) or, where commented, a value SyncSettings
87
+ # derives from another key (target from workdir, volume from the container/service
88
+ # name) — those stay unset so they keep tracking that key instead of going stale.
89
+ # A blank line separates every key from its neighbor; the gsub only indents
90
+ # non-blank lines so those separators stay actual blank lines, not trailing
91
+ # whitespace.
92
+ def sync_extras
93
+ <<~YAML.chomp.gsub(/^(?=.)/, ' ')
94
+ # optional; host path to mirror (default: wip.yml directory)
95
+ source: .
96
+
97
+ # optional; in-container mount point for the mirror (default: the container's workdir, else /app)
98
+ # target: /app
99
+
100
+ # optional; read-only host mount inside the container
101
+ mount: /host-src
102
+
103
+ # optional; named volume holding the mirrored tree (default: "<container>-src")
104
+ # volume: app-src
105
+
106
+ # optional; rsync --delete so removals on the host are mirrored too
107
+ delete: true
108
+
109
+ #{exclude_comment}
110
+ exclude:
111
+ #{exclude_list}
112
+
113
+ # optional; mirror binary to shell out to
114
+ command: rsync
115
+
116
+ # optional; extra flags appended to the mirror command
117
+ options: []
118
+
119
+ # optional; seconds between mirrors
120
+ interval: 2
121
+
122
+ # optional; exec (default, mirrors into the running container) | run (always a fresh container)
123
+ mode: exec
124
+
125
+ # only needed if sync.mode: run (or under mode: compose); image the mirror container runs
126
+ # image: your/image:tag
127
+
128
+ # alternative to image — let wip build a small dedicated mirror image itself
129
+ # build:
130
+ # dockerfile: |
131
+ # FROM alpine:latest
132
+ # RUN apk add --no-cache rsync
133
+
134
+ # optional (default: wip-sync-<container>:latest)
135
+ # tag: wip-sync-app:latest
136
+ YAML
137
+ end
138
+
139
+ def container_template
140
+ <<~YAML
141
+ version: 1
142
+
143
+ # container | compose | compose-native (see README)
144
+ mode: container
145
+
146
+ # TODO: rename freely, as long as it matches a key under dependencies: below
147
+ container: app
148
+
149
+ wslc:
150
+ # optional; wslc binary/path wip shells out to ("auto" resolves it for you)
151
+ command: auto
152
+
153
+ # optional; container network name (mode: container only)
154
+ # network: my-network
155
+
156
+ dependencies:
157
+ # this is the container wip creates, execs into, and runs commands in
158
+ app:
159
+ # TODO: image to run
160
+ image: your/image:tag
161
+
162
+ # TODO: adjust to match your image, or delete this line
163
+ workdir: /app
164
+
165
+ # optional; keep stdin open / allocate a tty
166
+ interactive: false
167
+
168
+ # optional; remove the container after each run
169
+ remove: true
170
+
171
+ # optional; environment variables passed to the container, e.g. {FOO: bar}
172
+ env: {}
173
+
174
+ # optional; published ports, e.g. ["3000:3000"]
175
+ ports: []
176
+
177
+ # optional; extra -v specs beyond the sync mounts below
178
+ volumes: []
179
+
180
+ #{COMMANDS_EXAMPLE}
181
+
182
+ # optional; mirrors the source into a named volume instead of bind-mounting it live
183
+ sync:
184
+ #{sync_extras}
185
+ YAML
186
+ end
187
+
74
188
  def compose_template
75
189
  <<~YAML
76
190
  version: 1
77
- mode: compose-native # wip parses #{compose_file} itself and drives wslc directly — no external
78
- # compose-for-wslc binary needed. Prefer a real compose tool instead? Use
79
- # mode: compose (see README "Compose mode") and set compose.command.
80
191
 
81
- # wslc: {} # optional; override which wslc binary/path wip shells out to (default: auto)
82
- # command: auto
192
+ # wip parses #{compose_file} itself and drives wslc directly — no external
193
+ # compose-for-wslc binary needed. Prefer a real compose tool instead? Use
194
+ # mode: compose (see README "Compose mode") and set compose.command.
195
+ mode: compose-native
196
+
197
+ wslc:
198
+ # optional; wslc binary/path wip shells out to ("auto" resolves it for you)
199
+ command: auto
83
200
 
84
201
  compose:
85
- service: app # TODO: which service in #{compose_file} wip run/exec/NAME target
86
- # file: #{compose_file} # optional; override which compose file to parse (default: auto-detected)
87
- # project: # optional; project/network name (default: wip.yml directory name)
88
- # command: # required under mode: compose (external compose-for-wslc binary); unused under compose-native
202
+ # TODO: which service in #{compose_file} wip run/exec/NAME target
203
+ service: app
204
+
205
+ # optional; override which compose file wip parses (default: auto-detected)
206
+ # file: #{compose_file}
207
+
208
+ # optional; project/network name (default: this directory's name)
209
+ # project: #{compose_project_default}
210
+
211
+ # only used under mode: compose (external compose-for-wslc binary); unused here under compose-native
212
+ # command:
213
+
214
+ # network: is derived from compose.project above (or this directory's name) — setting it
215
+ # directly conflicts with compose: (ConfigError), so it's intentionally left out here.
89
216
 
90
- # commands:
91
- # test: # example custom command, invoked as `wip test`
92
- # type: exec # optional; exec (default, runs in the running container) | run (fresh container) | build
93
- # command: bundle exec rspec # TODO
217
+ #{COMMANDS_EXAMPLE}
94
218
 
95
- #{SYNC_TEMPLATE}
219
+ # optional; mirrors the source into a named volume instead of bind-mounting it live
220
+ sync:
221
+ #{sync_extras}
96
222
  YAML
97
223
  end
98
224
  end
data/lib/wip/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Wip
4
- VERSION = '0.14.1'
4
+ VERSION = '0.15.0'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wslc-wip
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.1
4
+ version: 0.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wip contributors