@git.zone/tsdocker 1.17.2 โ†’ 2.0.2

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/readme.md CHANGED
@@ -12,13 +12,15 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community
12
12
 
13
13
  ### ๐ŸŽฏ Key Capabilities
14
14
 
15
- - ๐Ÿงช **Containerized Testing** โ€” Run your tests in pristine Docker environments
16
15
  - ๐Ÿ—๏ธ **Smart Docker Builds** โ€” Automatically discover, sort, and build Dockerfiles by dependency
17
16
  - ๐ŸŒ **True Multi-Architecture** โ€” Build for `amd64` and `arm64` simultaneously with Docker Buildx
18
17
  - ๐Ÿš€ **Multi-Registry Push** โ€” Ship to Docker Hub, GitLab, GitHub Container Registry, and more via OCI Distribution API
19
18
  - โšก **Parallel Builds** โ€” Level-based parallel builds with configurable concurrency
20
19
  - ๐Ÿ—„๏ธ **Persistent Local Registry** โ€” All images flow through a local OCI registry with persistent storage
21
20
  - ๐Ÿ“ฆ **Build Caching** โ€” Skip unchanged Dockerfiles with content-hash caching
21
+ - ๐ŸŽฏ **Dockerfile Filtering** โ€” Build or push only specific Dockerfiles using glob patterns
22
+ - ๐Ÿ” **Resilient Push** โ€” Automatic retry with exponential backoff, timeouts, and token refresh for rock-solid pushes
23
+ - ๐Ÿญ **CI-Safe Isolation** โ€” Unique sessions per invocation prevent collisions in parallel CI pipelines
22
24
  - ๐Ÿ”ง **Zero Config Start** โ€” Works out of the box, scales with your needs
23
25
 
24
26
  ## Installation
@@ -33,16 +35,6 @@ pnpm install --save-dev @git.zone/tsdocker
33
35
 
34
36
  ## Quick Start
35
37
 
36
- ### ๐Ÿงช Run Tests in Docker
37
-
38
- The simplest use case โ€” run your tests in a clean container:
39
-
40
- ```bash
41
- tsdocker
42
- ```
43
-
44
- This pulls your configured base image, mounts your project, and executes your test command in isolation.
45
-
46
38
  ### ๐Ÿ—๏ธ Build Docker Images
47
39
 
48
40
  Got `Dockerfile` files? Build them all with automatic dependency ordering:
@@ -68,15 +60,33 @@ tsdocker push
68
60
 
69
61
  # Push to a specific registry
70
62
  tsdocker push --registry=registry.gitlab.com
63
+
64
+ # Push without rebuilding (use existing images in local registry)
65
+ tsdocker push --no-build
71
66
  ```
72
67
 
73
- Under the hood, `tsdocker push` uses the **OCI Distribution API** to copy images directly from the local registry to remote registries. This means multi-arch manifest lists are preserved end-to-end โ€” no more single-platform-only pushes.
68
+ Under the hood, `tsdocker push` uses the **OCI Distribution API** to copy images directly from the local registry to remote registries. This means multi-arch manifest lists are preserved end-to-end โ€” no more single-platform-only pushes. Every request is protected with **automatic retry** (up to 6 attempts with exponential backoff) and **5-minute timeouts**, so transient network issues don't kill your push mid-transfer.
69
+
70
+ ### ๐ŸŽฏ Build Only Specific Dockerfiles
71
+
72
+ Target specific Dockerfiles by name pattern โ€” dependencies are resolved automatically:
73
+
74
+ ```bash
75
+ # Build only the base image
76
+ tsdocker build Dockerfile_base
77
+
78
+ # Build anything matching a glob pattern
79
+ tsdocker build Dockerfile_app*
80
+
81
+ # Push specific images only (skip build phase)
82
+ tsdocker push --no-build Dockerfile_api Dockerfile_web
83
+ ```
74
84
 
75
85
  ## CLI Commands
76
86
 
77
87
  | Command | Description |
78
88
  |---------|-------------|
79
- | `tsdocker` | Run tests in a fresh Docker container (legacy mode) |
89
+ | `tsdocker` | Show usage / man page |
80
90
  | `tsdocker build` | Build all Dockerfiles with dependency ordering |
81
91
  | `tsdocker push` | Build + push images to configured registries |
82
92
  | `tsdocker pull <registry>` | Pull images from a specific registry |
@@ -84,12 +94,12 @@ Under the hood, `tsdocker push` uses the **OCI Distribution API** to copy images
84
94
  | `tsdocker login` | Authenticate with configured registries |
85
95
  | `tsdocker list` | Display discovered Dockerfiles and their dependencies |
86
96
  | `tsdocker clean` | Interactively clean Docker environment |
87
- | `tsdocker vscode` | Launch containerized VS Code in browser |
88
97
 
89
98
  ### Build Flags
90
99
 
91
100
  | Flag | Description |
92
101
  |------|-------------|
102
+ | `<patterns>` | Positional Dockerfile name patterns (e.g. `Dockerfile_base`, `Dockerfile_app*`) |
93
103
  | `--platform=linux/arm64` | Override build platform for a single architecture |
94
104
  | `--timeout=600` | Build timeout in seconds |
95
105
  | `--no-cache` | Force rebuild without Docker layer cache |
@@ -99,6 +109,14 @@ Under the hood, `tsdocker push` uses the **OCI Distribution API** to copy images
99
109
  | `--parallel=8` | Parallel builds with custom concurrency |
100
110
  | `--context=mycontext` | Use a specific Docker context |
101
111
 
112
+ ### Push Flags
113
+
114
+ | Flag | Description |
115
+ |------|-------------|
116
+ | `<patterns>` | Positional Dockerfile name patterns to select which images to push |
117
+ | `--registry=<url>` | Push to a single specific registry instead of all configured |
118
+ | `--no-build` | Skip the build phase; only push existing images from local registry |
119
+
102
120
  ### Clean Flags
103
121
 
104
122
  | Flag | Description |
@@ -138,16 +156,6 @@ Configure tsdocker in your `package.json` or `npmextra.json` under the `@git.zon
138
156
  | `platforms` | `string[]` | `["linux/amd64"]` | Target architectures for multi-arch builds |
139
157
  | `testDir` | `string` | `./test` | Directory containing test scripts |
140
158
 
141
- #### Legacy Testing Options
142
-
143
- These options configure the `tsdocker` default command (containerized test runner):
144
-
145
- | Option | Type | Default | Description |
146
- |--------|------|---------|-------------|
147
- | `baseImage` | `string` | `hosttoday/ht-docker-node:npmdocker` | Docker image for test environment |
148
- | `command` | `string` | `npmci npm test` | Command to run inside the container |
149
- | `dockerSock` | `boolean` | `false` | Mount Docker socket for DinD scenarios |
150
-
151
159
  ## Architecture: How tsdocker Works
152
160
 
153
161
  tsdocker uses a **local OCI registry** as the canonical store for all built images. This design solves fundamental problems with Docker's local daemon, which cannot hold multi-architecture manifest lists.
@@ -155,36 +163,37 @@ tsdocker uses a **local OCI registry** as the canonical store for all built imag
155
163
  ### ๐Ÿ“ Build Flow
156
164
 
157
165
  ```
158
- โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
159
- โ”‚ tsdocker build โ”‚
160
- โ”‚ โ”‚
161
- โ”‚ 1. Start local registry (localhost:5234) โ”‚
162
- โ”‚ โ””โ”€โ”€ Persistent volume: .nogit/docker-registry/
163
- โ”‚ โ”‚
164
- โ”‚ 2. For each Dockerfile (topological order): โ”‚
165
- โ”‚ โ”œโ”€โ”€ Multi-platform: buildx --push โ†’ registry โ”‚
166
- โ”‚ โ””โ”€โ”€ Single-platform: docker build โ†’ registry โ”‚
167
- โ”‚ โ”‚
168
- โ”‚ 3. Stop local registry (data persists on disk) โ”‚
169
- โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
166
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
167
+ โ”‚ tsdocker build โ”‚
168
+ โ”‚ โ”‚
169
+ โ”‚ 1. Start local registry (localhost:<dynamic-port>) โ”‚
170
+ โ”‚ โ””โ”€โ”€ Persistent volume: .nogit/docker-registry/ โ”‚
171
+ โ”‚ โ”‚
172
+ โ”‚ 2. For each Dockerfile (topological order): โ”‚
173
+ โ”‚ โ”œโ”€โ”€ Multi-platform: buildx --push โ†’ registry โ”‚
174
+ โ”‚ โ””โ”€โ”€ Single-platform: docker build โ†’ registry โ”‚
175
+ โ”‚ โ”‚
176
+ โ”‚ 3. Stop local registry (data persists on disk) โ”‚
177
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
170
178
  ```
171
179
 
172
180
  ### ๐Ÿ“ค Push Flow
173
181
 
174
182
  ```
175
- โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
176
- โ”‚ tsdocker push โ”‚
177
- โ”‚ โ”‚
178
- โ”‚ 1. Start local registry (loads persisted data) โ”‚
179
- โ”‚ โ”‚
180
- โ”‚ 2. For each image ร— each remote registry: โ”‚
181
- โ”‚ โ””โ”€โ”€ OCI Distribution API copy: โ”‚
182
- โ”‚ โ”œโ”€โ”€ Fetch manifest (single or multi-arch) โ”‚
183
- โ”‚ โ”œโ”€โ”€ Copy blobs (skip if already exist) โ”‚
184
- โ”‚ โ””โ”€โ”€ Push manifest with destination tag โ”‚
185
- โ”‚ โ”‚
186
- โ”‚ 3. Stop local registry โ”‚
187
- โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
183
+ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
184
+ โ”‚ tsdocker push โ”‚
185
+ โ”‚ โ”‚
186
+ โ”‚ 1. Start local registry (loads persisted data) โ”‚
187
+ โ”‚ โ”‚
188
+ โ”‚ 2. For each image ร— each remote registry: โ”‚
189
+ โ”‚ โ””โ”€โ”€ OCI Distribution API copy (with retry): โ”‚
190
+ โ”‚ โ”œโ”€โ”€ Fetch manifest (single or multi-arch) โ”‚
191
+ โ”‚ โ”œโ”€โ”€ Copy blobs (skip if already exist) โ”‚
192
+ โ”‚ โ”œโ”€โ”€ Retry up to 6ร— with exponential backoff โ”‚
193
+ โ”‚ โ””โ”€โ”€ Push manifest with destination tag โ”‚
194
+ โ”‚ โ”‚
195
+ โ”‚ 3. Stop local registry โ”‚
196
+ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
188
197
  ```
189
198
 
190
199
  ### ๐Ÿ”‘ Why a Local Registry?
@@ -196,6 +205,49 @@ tsdocker uses a **local OCI registry** as the canonical store for all built imag
196
205
  | Images lost between build and push phases | Persistent storage at `.nogit/docker-registry/` survives restarts |
197
206
  | Redundant blob uploads on incremental pushes | HEAD checks skip blobs that already exist on the remote |
198
207
 
208
+ ### ๐Ÿ” Resilient Push
209
+
210
+ The OCI Distribution API client wraps every HTTP request with:
211
+
212
+ - **Timeouts** โ€” 5-minute timeout for blob operations, 30-second timeout for auth/metadata calls via `AbortSignal.timeout()`
213
+ - **Automatic Retry** โ€” Up to 6 attempts with exponential backoff (1s โ†’ 2s โ†’ 4s โ†’ 8s โ†’ 16s โ†’ 32s)
214
+ - **Smart Retry Logic** โ€” Retries on network errors (`ECONNRESET`, `fetch failed`) and 5xx server errors; does NOT retry 4xx client errors
215
+ - **Token Refresh** โ€” On 401 responses, the cached auth token is cleared so the next retry re-authenticates automatically
216
+
217
+ This means transient issues like stale connection pools, brief network blips, or token expiry during long multi-arch pushes (56+ blob operations) are handled gracefully instead of killing the entire transfer.
218
+
219
+ ### ๐Ÿญ CI-Safe Session Isolation
220
+
221
+ Every tsdocker invocation gets its own **session** with unique:
222
+
223
+ - **Session ID** โ€” Random 8-char hex (override with `TSDOCKER_SESSION_ID`)
224
+ - **Registry port** โ€” Dynamically allocated (override with `TSDOCKER_REGISTRY_PORT`)
225
+ - **Registry container** โ€” Named `tsdocker-registry-<sessionId>`
226
+ - **Builder suffix** โ€” In CI, the buildx builder gets a `-<sessionId>` suffix to prevent collisions
227
+
228
+ This prevents resource conflicts when multiple CI jobs run tsdocker in parallel. Auto-detected CI systems:
229
+
230
+ | Environment Variable | CI System |
231
+ |---------------------|-----------|
232
+ | `GITEA_ACTIONS` | Gitea Actions |
233
+ | `GITHUB_ACTIONS` | GitHub Actions |
234
+ | `GITLAB_CI` | GitLab CI |
235
+ | `CI` | Generic CI |
236
+
237
+ In local dev, no suffix is added โ€” keeping a persistent builder for faster rebuilds.
238
+
239
+ ### ๐Ÿ” Docker Context & Topology Detection
240
+
241
+ tsdocker automatically detects your Docker environment topology:
242
+
243
+ | Topology | Detection | Meaning |
244
+ |----------|-----------|---------|
245
+ | `local` | Default | Standard Docker installation on the host |
246
+ | `socket-mount` | `/.dockerenv` exists | Running inside a container with Docker socket mounted |
247
+ | `dind` | `DOCKER_HOST` starts with `tcp://` | Docker-in-Docker setup |
248
+
249
+ Context-aware builder names (`tsdocker-builder-<context>`) prevent conflicts across Docker contexts. Rootless Docker configurations trigger appropriate warnings.
250
+
199
251
  ## Registry Authentication
200
252
 
201
253
  ### Environment Variables
@@ -213,7 +265,7 @@ export DOCKER_REGISTRY_PASSWORD="password"
213
265
 
214
266
  ### Docker Config Fallback
215
267
 
216
- When pushing, tsdocker will also read credentials from `~/.docker/config.json` if no explicit credentials are provided via environment variables. This means `docker login` credentials work automatically.
268
+ When pushing, tsdocker will also read credentials from `~/.docker/config.json` if no explicit credentials are provided via environment variables. This means `docker login` credentials work automatically. Docker Hub special cases (`docker.io`, `index.docker.io`, `registry-1.docker.io`) are all recognized.
217
269
 
218
270
  ### Login Command
219
271
 
@@ -270,6 +322,26 @@ tsdocker discovers files matching `Dockerfile*`:
270
322
  | `Dockerfile_alpine` | `alpine` |
271
323
  | `Dockerfile_##version##` | Uses `package.json` version |
272
324
 
325
+ ### ๐ŸŽฏ Dockerfile Filtering
326
+
327
+ Build or push only the Dockerfiles you need. Positional arguments are matched against Dockerfile basenames as glob patterns:
328
+
329
+ ```bash
330
+ # Build a single Dockerfile
331
+ tsdocker build Dockerfile_base
332
+
333
+ # Glob patterns with * and ? wildcards
334
+ tsdocker build Dockerfile_app*
335
+
336
+ # Multiple patterns
337
+ tsdocker build Dockerfile_base Dockerfile_web
338
+
339
+ # Push specific images without rebuilding
340
+ tsdocker push --no-build Dockerfile_api
341
+ ```
342
+
343
+ When filtering for `build`, **dependencies are auto-resolved**: if `Dockerfile_app` depends on `Dockerfile_base`, specifying only `Dockerfile_app` will automatically include `Dockerfile_base` in the build order.
344
+
273
345
  ### ๐Ÿ”— Dependency-Aware Builds
274
346
 
275
347
  If you have multiple Dockerfiles that depend on each other:
@@ -347,20 +419,6 @@ Use different repository names for different registries:
347
419
 
348
420
  When pushing, tsdocker maps the local repo name to the registry-specific path. For example, a locally built `myproject:latest` becomes `registry.gitlab.com/mygroup/myproject:latest` and `docker.io/myuser/myproject:latest`.
349
421
 
350
- ### ๐Ÿณ Docker-in-Docker Testing
351
-
352
- Test Docker-related tools by mounting the Docker socket:
353
-
354
- ```json
355
- {
356
- "@git.zone/tsdocker": {
357
- "baseImage": "docker:latest",
358
- "command": "docker version && docker ps",
359
- "dockerSock": true
360
- }
361
- }
362
- ```
363
-
364
422
  ### ๐Ÿ“‹ Listing Dockerfiles
365
423
 
366
424
  Inspect your project's Dockerfiles and their relationships:
@@ -449,6 +507,19 @@ build-and-push:
449
507
  DOCKER_REGISTRY_1: "ghcr.io|${{ github.actor }}|${{ secrets.GITHUB_TOKEN }}"
450
508
  ```
451
509
 
510
+ **Gitea Actions:**
511
+
512
+ ```yaml
513
+ - name: Build and Push
514
+ run: |
515
+ npm install -g @git.zone/tsdocker
516
+ tsdocker push
517
+ env:
518
+ DOCKER_REGISTRY_1: "gitea.example.com|${{ secrets.REGISTRY_USER }}|${{ secrets.REGISTRY_PASSWORD }}"
519
+ ```
520
+
521
+ tsdocker auto-detects all three CI systems and enables session isolation automatically โ€” no extra configuration needed.
522
+
452
523
  ## TypeScript API
453
524
 
454
525
  tsdocker can also be used programmatically:
@@ -458,10 +529,6 @@ import { TsDockerManager } from '@git.zone/tsdocker/dist_ts/classes.tsdockermana
458
529
  import type { ITsDockerConfig } from '@git.zone/tsdocker/dist_ts/interfaces/index.js';
459
530
 
460
531
  const config: ITsDockerConfig = {
461
- baseImage: 'node:20',
462
- command: 'npm test',
463
- dockerSock: false,
464
- keyValueObject: {},
465
532
  registries: ['docker.io'],
466
533
  platforms: ['linux/amd64', 'linux/arm64'],
467
534
  };
@@ -472,6 +539,25 @@ await manager.build({ parallel: true });
472
539
  await manager.push();
473
540
  ```
474
541
 
542
+ ## Environment Variables
543
+
544
+ ### CI & Session Control
545
+
546
+ | Variable | Description |
547
+ |----------|-------------|
548
+ | `TSDOCKER_SESSION_ID` | Override the auto-generated session ID (default: random 8-char hex) |
549
+ | `TSDOCKER_REGISTRY_PORT` | Override the dynamically allocated local registry port |
550
+ | `CI` | Generic CI detection (also `GITHUB_ACTIONS`, `GITLAB_CI`, `GITEA_ACTIONS`) |
551
+
552
+ ### Registry Credentials
553
+
554
+ | Variable | Description |
555
+ |----------|-------------|
556
+ | `DOCKER_REGISTRY_1` through `DOCKER_REGISTRY_10` | Pipe-delimited: `registry\|username\|password` |
557
+ | `DOCKER_REGISTRY_URL` | Registry URL for single-registry setup |
558
+ | `DOCKER_REGISTRY_USER` | Username for single-registry setup |
559
+ | `DOCKER_REGISTRY_PASSWORD` | Password for single-registry setup |
560
+
475
561
  ## Requirements
476
562
 
477
563
  - **Docker** โ€” Docker Engine 20+ or Docker Desktop
@@ -507,6 +593,15 @@ tsdocker login
507
593
 
508
594
  tsdocker also falls back to `~/.docker/config.json` โ€” ensure you've run `docker login` for your target registries.
509
595
 
596
+ ### Push fails with "fetch failed"
597
+
598
+ tsdocker automatically retries failed requests up to 6 times with exponential backoff. If pushes still fail:
599
+
600
+ - Check network connectivity to the target registry
601
+ - Verify your credentials haven't expired
602
+ - Look for retry log messages (`fetch failed (attempt X/6)`) to diagnose the pattern
603
+ - Large layers may need longer timeouts โ€” the default 5-minute timeout per request should cover most cases
604
+
510
605
  ### Circular dependency detected
511
606
 
512
607
  Review your Dockerfiles' `FROM` statements โ€” you have images depending on each other in a loop.
@@ -522,16 +617,6 @@ node_modules
522
617
  dist_ts
523
618
  ```
524
619
 
525
- ## Migration from Legacy
526
-
527
- Previously published as `npmdocker`, now `@git.zone/tsdocker`:
528
-
529
- | Old | New |
530
- |-----|-----|
531
- | `npmdocker` command | `tsdocker` command |
532
- | `"npmdocker"` config key | `"@git.zone/tsdocker"` config key |
533
- | CommonJS | ESM with `.js` imports |
534
-
535
620
  ## License and Legal Information
536
621
 
537
622
  This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./LICENSE) file.
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@git.zone/tsdocker',
6
- version: '1.17.2',
6
+ version: '2.0.2',
7
7
  description: 'develop npm modules cross platform with docker'
8
8
  }
@@ -29,7 +29,7 @@ export class RegistryCopy {
29
29
  url: string,
30
30
  options: RequestInit & { duplex?: string },
31
31
  timeoutMs: number = 300_000,
32
- maxRetries: number = 3,
32
+ maxRetries: number = 6,
33
33
  ): Promise<Response> {
34
34
  const method = (options.method || 'GET').toUpperCase();
35
35
  let lastError: Error | null = null;
@@ -1,15 +1,7 @@
1
1
  /**
2
2
  * Configuration interface for tsdocker
3
- * Extends legacy config with new Docker build capabilities
4
3
  */
5
4
  export interface ITsDockerConfig {
6
- // Legacy (backward compatible)
7
- baseImage: string;
8
- command: string;
9
- dockerSock: boolean;
10
- keyValueObject: { [key: string]: any };
11
-
12
- // New Docker build config
13
5
  registries?: string[];
14
6
  registryRepoMap?: { [registry: string]: string };
15
7
  buildArgEnvMap?: { [dockerArg: string]: string };
@@ -3,7 +3,6 @@ import * as paths from './tsdocker.paths.js';
3
3
 
4
4
  // modules
5
5
  import * as ConfigModule from './tsdocker.config.js';
6
- import * as DockerModule from './tsdocker.docker.js';
7
6
 
8
7
  import { logger, ora } from './tsdocker.logging.js';
9
8
  import { TsDockerManager } from './classes.tsdockermanager.js';
@@ -14,16 +13,69 @@ import { commitinfo } from './00_commitinfo_data.js';
14
13
  const tsdockerCli = new plugins.smartcli.Smartcli();
15
14
  tsdockerCli.addVersion(commitinfo.version);
16
15
 
16
+ const printManPage = () => {
17
+ const manPage = `
18
+ TSDOCKER(1) User Commands TSDOCKER(1)
19
+
20
+ NAME
21
+ tsdocker - build, test, and push Docker images
22
+
23
+ VERSION
24
+ ${commitinfo.version}
25
+
26
+ SYNOPSIS
27
+ tsdocker <command> [options]
28
+
29
+ COMMANDS
30
+ build [patterns...] [flags] Build Dockerfiles in dependency order
31
+ push [patterns...] [flags] Build and push images to registries
32
+ pull <registry-url> Pull images from a registry
33
+ test [flags] Build and run container test scripts
34
+ login Authenticate with configured registries
35
+ list List discovered Dockerfiles
36
+ clean [-y] [--all] Interactive Docker resource cleanup
37
+
38
+ BUILD / PUSH OPTIONS
39
+ --platform=<p> Target platform (e.g. linux/arm64)
40
+ --timeout=<s> Build timeout in seconds
41
+ --no-cache Rebuild without Docker layer cache
42
+ --cached Skip builds when Dockerfile is unchanged
43
+ --verbose Stream raw docker build output
44
+ --parallel[=<n>] Parallel builds (optional concurrency limit)
45
+ --context=<name> Docker context to use
46
+
47
+ PUSH-ONLY OPTIONS
48
+ --registry=<url> Push to a specific registry
49
+ --no-build Push already-built images (skip build step)
50
+
51
+ CLEAN OPTIONS
52
+ -y Auto-confirm all prompts
53
+ --all Include all images and volumes (not just dangling)
54
+
55
+ CONFIGURATION
56
+ Configure via npmextra.json under the "@git.zone/tsdocker" key:
57
+
58
+ registries Array of registry URLs to push to
59
+ registryRepoMap Map of registry URL to repo path overrides
60
+ buildArgEnvMap Map of Docker build-arg names to env var names
61
+ platforms Array of target platforms (default: ["linux/amd64"])
62
+ push Boolean, auto-push after build
63
+ testDir Directory containing test_*.sh scripts
64
+
65
+ EXAMPLES
66
+ tsdocker build
67
+ tsdocker build Dockerfile_app --platform=linux/arm64
68
+ tsdocker push --registry=ghcr.io
69
+ tsdocker test --verbose
70
+ tsdocker clean -y --all
71
+ `;
72
+ console.log(manPage);
73
+ };
74
+
17
75
  export let run = () => {
18
- // Default command: run tests in container (legacy behavior)
19
- tsdockerCli.standardCommand().subscribe(async argvArg => {
20
- const configArg = await ConfigModule.run().then(DockerModule.run);
21
- if (configArg.exitCode === 0) {
22
- logger.log('success', 'container ended all right!');
23
- } else {
24
- logger.log('error', `container ended with error! Exit Code is ${configArg.exitCode}`);
25
- process.exit(1);
26
- }
76
+ // Default command: print man page
77
+ tsdockerCli.standardCommand().subscribe(async () => {
78
+ printManPage();
27
79
  });
28
80
 
29
81
  /**
@@ -228,24 +280,6 @@ export let run = () => {
228
280
  }
229
281
  });
230
282
 
231
- /**
232
- * this command is executed inside docker and meant for use from outside docker
233
- */
234
- tsdockerCli.addCommand('runinside').subscribe(async argvArg => {
235
- logger.log('ok', 'Allright. We are now in Docker!');
236
- ora.text('now trying to run your specified command');
237
- const configArg = await ConfigModule.run();
238
- const smartshellInstance = new plugins.smartshell.Smartshell({
239
- executor: 'bash'
240
- });
241
- ora.stop();
242
- await smartshellInstance.exec(configArg.command).then(response => {
243
- if (response.exitCode !== 0) {
244
- process.exit(1);
245
- }
246
- });
247
- });
248
-
249
283
  tsdockerCli.addCommand('clean').subscribe(async argvArg => {
250
284
  try {
251
285
  const autoYes = !!argvArg.y;
@@ -443,19 +477,5 @@ export let run = () => {
443
477
  }
444
478
  });
445
479
 
446
- tsdockerCli.addCommand('vscode').subscribe(async argvArg => {
447
- const smartshellInstance = new plugins.smartshell.Smartshell({
448
- executor: 'bash'
449
- });
450
- logger.log('ok', `Starting vscode in cwd ${paths.cwd}`);
451
- await smartshellInstance.execAndWaitForLine(
452
- `docker run -p 127.0.0.1:8443:8443 -v "${
453
- paths.cwd
454
- }:/home/coder/project" registry.gitlab.com/hosttoday/ht-docker-vscode --allow-http --no-auth`,
455
- /Connected to shared process/
456
- );
457
- await plugins.smartopen.openUrl('testing-vscode.git.zone:8443');
458
- });
459
-
460
480
  tsdockerCli.startParse();
461
481
  };
@@ -1,34 +1,10 @@
1
1
  import * as plugins from './tsdocker.plugins.js';
2
2
  import * as paths from './tsdocker.paths.js';
3
- import * as fs from 'fs';
4
3
  import type { ITsDockerConfig } from './interfaces/index.js';
5
4
 
6
- // Re-export ITsDockerConfig as IConfig for backward compatibility
7
- export type IConfig = ITsDockerConfig & {
8
- exitCode?: number;
9
- };
10
-
11
- const getQenvKeyValueObject = async () => {
12
- let qenvKeyValueObjectArray: { [key: string]: string | number };
13
- if (fs.existsSync(plugins.path.join(paths.cwd, 'qenv.yml'))) {
14
- qenvKeyValueObjectArray = new plugins.qenv.Qenv(paths.cwd, '.nogit/').keyValueObject;
15
- } else {
16
- qenvKeyValueObjectArray = {};
17
- }
18
- return qenvKeyValueObjectArray;
19
- };
20
-
21
- const buildConfig = async (qenvKeyValueObjectArg: { [key: string]: string | number }) => {
5
+ const buildConfig = async (): Promise<ITsDockerConfig> => {
22
6
  const npmextra = new plugins.npmextra.Npmextra(paths.cwd);
23
- const config = npmextra.dataFor<IConfig>('@git.zone/tsdocker', {
24
- // Legacy options (backward compatible)
25
- baseImage: 'hosttoday/ht-docker-node:npmdocker',
26
- init: 'rm -rf node_nodules/ && yarn install',
27
- command: 'npmci npm test',
28
- dockerSock: false,
29
- keyValueObject: qenvKeyValueObjectArg,
30
-
31
- // New Docker build options
7
+ const config = npmextra.dataFor<ITsDockerConfig>('@git.zone/tsdocker', {
32
8
  registries: [],
33
9
  registryRepoMap: {},
34
10
  buildArgEnvMap: {},
@@ -39,7 +15,6 @@ const buildConfig = async (qenvKeyValueObjectArg: { [key: string]: string | numb
39
15
  return config;
40
16
  };
41
17
 
42
- export let run = async (): Promise<IConfig> => {
43
- const config = await getQenvKeyValueObject().then(buildConfig);
44
- return config;
18
+ export let run = async (): Promise<ITsDockerConfig> => {
19
+ return buildConfig();
45
20
  };
@@ -11,4 +11,3 @@ export let cwd = process.cwd();
11
11
  export let packageBase = plugins.path.join(__dirname, '../');
12
12
  export let assets = plugins.path.join(packageBase, 'assets/');
13
13
  fs.mkdirSync(assets, { recursive: true });
14
- export let npmdockerFile = plugins.path.join(cwd, 'npmdocker');
@@ -3,17 +3,13 @@ import * as lik from '@push.rocks/lik';
3
3
  import * as npmextra from '@push.rocks/npmextra';
4
4
  import * as path from 'path';
5
5
  import * as projectinfo from '@push.rocks/projectinfo';
6
- import * as smartpromise from '@push.rocks/smartpromise';
7
- import * as qenv from '@push.rocks/qenv';
8
6
  import * as smartcli from '@push.rocks/smartcli';
9
7
  import { SmartFs, SmartFsProviderNode } from '@push.rocks/smartfs';
10
8
  import * as smartlog from '@push.rocks/smartlog';
11
9
  import * as smartlogDestinationLocal from '@push.rocks/smartlog-destination-local';
12
10
  import * as smartlogSouceOra from '@push.rocks/smartlog-source-ora';
13
- import * as smartopen from '@push.rocks/smartopen';
14
11
  import * as smartinteract from '@push.rocks/smartinteract';
15
12
  import * as smartshell from '@push.rocks/smartshell';
16
- import * as smartstring from '@push.rocks/smartstring';
17
13
 
18
14
  // Create smartfs instance
19
15
  export const smartfs = new SmartFs(new SmartFsProviderNode());
@@ -23,14 +19,10 @@ export {
23
19
  npmextra,
24
20
  path,
25
21
  projectinfo,
26
- smartpromise,
27
- qenv,
28
22
  smartcli,
29
23
  smartinteract,
30
24
  smartlog,
31
25
  smartlogDestinationLocal,
32
26
  smartlogSouceOra,
33
- smartopen,
34
27
  smartshell,
35
- smartstring
36
28
  };
package/assets/Dockerfile DELETED
@@ -1,6 +0,0 @@
1
- FROM hosttoday/ht-docker-node:npmci
2
- RUN yarn global add @git.zone/tsdocker
3
- COPY ./ /workspace
4
- WORKDIR /workspace
5
- ENV CI=true
6
- CMD ["tsdocker","runinside"];
@@ -1,2 +0,0 @@
1
- import type { IConfig } from './tsdocker.config.js';
2
- export declare let run: (configArg: IConfig) => Promise<IConfig>;