@ship.zone/szci 7.1.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.
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * SZCI npm wrapper
5
+ * This script executes the appropriate pre-compiled binary based on the current platform
6
+ */
7
+
8
+ import { spawn } from 'child_process';
9
+ import { fileURLToPath } from 'url';
10
+ import { dirname, join } from 'path';
11
+ import { existsSync } from 'fs';
12
+ import { platform, arch } from 'os';
13
+
14
+ const __filename = fileURLToPath(import.meta.url);
15
+ const __dirname = dirname(__filename);
16
+
17
+ /**
18
+ * Get the binary name for the current platform
19
+ */
20
+ function getBinaryName() {
21
+ const plat = platform();
22
+ const architecture = arch();
23
+
24
+ // Map Node's platform/arch to our binary naming
25
+ const platformMap = {
26
+ 'darwin': 'macos',
27
+ 'linux': 'linux',
28
+ 'win32': 'windows'
29
+ };
30
+
31
+ const archMap = {
32
+ 'x64': 'x64',
33
+ 'arm64': 'arm64'
34
+ };
35
+
36
+ const mappedPlatform = platformMap[plat];
37
+ const mappedArch = archMap[architecture];
38
+
39
+ if (!mappedPlatform || !mappedArch) {
40
+ console.error(`Error: Unsupported platform/architecture: ${plat}/${architecture}`);
41
+ console.error('Supported platforms: Linux, macOS, Windows');
42
+ console.error('Supported architectures: x64, arm64');
43
+ process.exit(1);
44
+ }
45
+
46
+ // Construct binary name
47
+ let binaryName = `szci-${mappedPlatform}-${mappedArch}`;
48
+ if (plat === 'win32') {
49
+ binaryName += '.exe';
50
+ }
51
+
52
+ return binaryName;
53
+ }
54
+
55
+ /**
56
+ * Execute the binary
57
+ */
58
+ function executeBinary() {
59
+ const binaryName = getBinaryName();
60
+ const binaryPath = join(__dirname, '..', 'dist', 'binaries', binaryName);
61
+
62
+ // Check if binary exists
63
+ if (!existsSync(binaryPath)) {
64
+ console.error(`Error: Binary not found at ${binaryPath}`);
65
+ console.error('This might happen if:');
66
+ console.error('1. The postinstall script failed to run');
67
+ console.error('2. The platform is not supported');
68
+ console.error('3. The package was not installed correctly');
69
+ console.error('');
70
+ console.error('Try reinstalling the package:');
71
+ console.error(' npm uninstall -g @ship.zone/szci');
72
+ console.error(' npm install -g @ship.zone/szci');
73
+ process.exit(1);
74
+ }
75
+
76
+ // Spawn the binary with all arguments passed through
77
+ const child = spawn(binaryPath, process.argv.slice(2), {
78
+ stdio: 'inherit',
79
+ shell: false
80
+ });
81
+
82
+ // Handle child process events
83
+ child.on('error', (err) => {
84
+ console.error(`Error executing szci: ${err.message}`);
85
+ process.exit(1);
86
+ });
87
+
88
+ child.on('exit', (code, signal) => {
89
+ if (signal) {
90
+ process.kill(process.pid, signal);
91
+ } else {
92
+ process.exit(code || 0);
93
+ }
94
+ });
95
+
96
+ // Forward signals to child process
97
+ const signals = ['SIGINT', 'SIGTERM', 'SIGHUP'];
98
+ signals.forEach(signal => {
99
+ process.on(signal, () => {
100
+ if (!child.killed) {
101
+ child.kill(signal);
102
+ }
103
+ });
104
+ });
105
+ }
106
+
107
+ // Execute
108
+ executeBinary();
package/changelog.md ADDED
@@ -0,0 +1,136 @@
1
+ # Changelog
2
+
3
+ ## 2026-02-07 - 7.1.0 - feat(installer)
4
+ switch installer/docs to use main branch; add automated installer instructions and update CI examples to use the installer; add release registries and access level in npmextra.json
5
+
6
+ - Replaced master branch URLs with main in install.sh and README examples
7
+ - Added "Automated Installer (Recommended)" section to README with curl install examples (including versioned install)
8
+ - Replaced npm install -g @ship.zone/szci in CI examples with the curl-based installer invocation (some uses sudo)
9
+ - Updated npmextra.json: removed npmAccessLevel for @ship.zone/szci and added release.registries and release.accessLevel entries
10
+
11
+ ## 2026-02-06 - 7.0.0 - BREAKING CHANGE(szci)
12
+ delegate Docker operations to @git.zone/tsdocker, remove internal Docker managers and deprecated modules, simplify CLI and env var handling
13
+
14
+ - Delegate all Docker actions to @git.zone/tsdocker via npx; SzciDockerManager now bridges SZCI_LOGIN_DOCKER* and CI_JOB_TOKEN to DOCKER_REGISTRY_N and invokes npx @git.zone/tsdocker for build/login/push/pull/test.
15
+ - Removed internal Docker implementation: Dockerfile, DockerRegistry, RegistryStorage, related helpers and plugin wrappers removed from ts/manager.docker.
16
+ - Removed Cloudron manager and other deprecated modules and their plugin shims: manager.cloudron, mod_clean, mod_command, mod_precheck, mod_trigger (and corresponding CLI commands: cloudron, clean, command, precheck, trigger).
17
+ - CLI and exports simplified: Dockerfile export removed from mod.ts; Szci CLI now delegates docker command to the simplified SzciDockerManager.
18
+ - Updated environment handling: bridges SZCI_LOGIN_DOCKER* → DOCKER_REGISTRY_N and auto-bridges GitLab CI CI_JOB_TOKEN to DOCKER_REGISTRY_0.
19
+ - Node.js default mappings updated: stable→22, lts→20, legacy→18.
20
+ - Dependencies and plugins cleaned-up: removed unused/obsolete deps (e.g. @push.rocks/lik, smartdelay, through2) from deno.json and szci.plugins.ts.
21
+ - Docs updated (readme.md, readme.hints.md) to reflect architecture, tsdocker delegation, env var bridging and migration notes from npmci.
22
+ - BREAKING: CI configs and any workflows relying on internal Docker classes or the removed CLI commands must be updated to use tsdocker and the new env var/command flows.
23
+
24
+ ## 2025-10-26 - 6.0.1 - fix(tests)
25
+ Migrate tests to Deno native runner and update Deno config
26
+
27
+ - Convert test suites from tap/tapbundle to Deno.test and @std/assert
28
+ - Replace CommonJS-style runtime imports with .ts module imports for Deno (test files updated)
29
+ - Use Deno.env.set to configure test environment variables and restore working directory after tests
30
+ - Update test/test.cloudly.ts to import CloudlyConnector directly and disable TLS verification for tests
31
+ - Adjust deno.json version field (6.0.0 -> 5.0.0) as part of Deno configuration changes
32
+ - Add local project .claude/settings.local.json for tooling permissions
33
+
34
+ ## 2025-10-26 - 6.0.0 - BREAKING CHANGE(szci)
35
+ Rename project from npmci to szci and migrate runtime to Deno; add compiled binaries, installer and wrapper; update imports, env handling and package metadata
36
+
37
+ - Major rename/refactor: Npmci -> Szci across the codebase (classes, filenames, modules and exports).
38
+ - Migrate runtime to Deno: add deno.json, mod.ts entry point, use Deno.std imports and .ts module imports throughout.
39
+ - Add compilation and distribution tooling: scripts/compile-all.sh, scripts/install-binary.js, bin/szci-wrapper.js and dist/binaries layout for prebuilt executables.
40
+ - Package metadata updated: package.json renamed/rewritten for @ship.zone/szci and bumped to 5.0.0, updated publishConfig, files and scripts.
41
+ - Environment API changes: replaced process.env usages with Deno.env accessors and updated path constants (Szci paths).
42
+ - Refactored helper modules: npmci.bash -> szci.bash, updated smartshell/bash wrappers and other manager modules to Deno patterns.
43
+ - Tests and imports updated to new module paths and package layout; .gitignore updated to ignore deno artifacts.
44
+ - Breaking changes to callers: CLI name, class names, programmatic API, binary installation and environment handling have changed and may require updates in integrations and CI configurations.
45
+
46
+ ## 2024-11-17 - 4.1.37 - fix(docker)
47
+ Enhanced base image extraction logic from Dockerfile
48
+
49
+ - Improved dockerBaseImage to accurately extract base images considering ARG variables.
50
+ - Added support for parsing Dockerfile content without external libraries.
51
+ - Enhanced error handling for missing FROM instructions.
52
+
53
+ ## 2024-11-17 - 4.1.36 - fix(docker)
54
+ Improve logging for Dockerfile build order with base image details.
55
+
56
+ - Enhance logging in Dockerfile sorting process to include base image information.
57
+
58
+ ## 2024-11-17 - 4.1.35 - fix(docker)
59
+ Fix Dockerfile dependency sorting and enhance environment variable handling for GitHub repos
60
+
61
+ - Refined the algorithm for sorting Dockerfiles based on dependencies to ensure proper build order.
62
+ - Enhanced environment variable handling in the NpmciEnv class to support conditional assignments.
63
+ - Updated various dependencies in package.json for improved performance and compatibility.
64
+ - Added error handling to circular dependency detection in Dockerfile sorting.
65
+
66
+ ## 2024-11-05 - 4.1.34 - fix(connector)
67
+ Remove unused typedrequest implementation in cloudlyconnector
68
+
69
+ - Removed commented out code that initialized typedrequest in CloudlyConnector.
70
+
71
+ ## 2024-11-05 - 4.1.33 - fix(core)
72
+ Updated dependencies and improved npm preparation logic.
73
+
74
+ - Updated @git.zone/tsbuild from ^2.1.84 to ^2.2.0.
75
+ - Updated @git.zone/tsrun from ^1.2.49 to ^1.3.3.
76
+ - Updated @types/node from ^22.7.9 to ^22.8.7.
77
+ - Updated @serve.zone/api from ^1.2.1 to ^4.3.1.
78
+ - Improved npm preparation logic to handle empty tokens gracefully.
79
+
80
+ ## 2024-10-23 - 4.1.32 - fix(dependencies)
81
+ Update project dependencies to latest versions
82
+
83
+ - Updated development dependencies, including @git.zone/tsbuild and @git.zone/tsrun.
84
+ - Updated production dependencies such as @api.global/typedrequest and @push.rocks/smartfile.
85
+
86
+ ## 2022-10-24 - 4.0.11 - prerelease
87
+ now includes a precheck for more generic runner execution
88
+
89
+ - Implemented a precheck feature for runners.
90
+
91
+ ## 2022-10-09 to 2022-10-11 - 4.0.0 to 4.0.10 - migration
92
+ internal migrations and fixes
93
+
94
+ - Major switch to ESM style module: **BREAKING CHANGE**.
95
+ - Multiple fixes in core functionalities and module updates.
96
+
97
+ ## 2019-11-26 - 3.1.73 - fixes
98
+ correctly setting npm cache and other updates
99
+
100
+ - Ensured correct npm cache setting during preparation.
101
+ - Various core updates.
102
+
103
+ ## 2018-12-23 - 3.1.19 - privacy updates
104
+ enhanced mirroring controls for private code
105
+
106
+ - Now refusing to mirror private code.
107
+
108
+ ## 2018-11-24 - 3.1.2 - ci improvement
109
+ removed unnecessary build dependency
110
+
111
+ - Removed npmts build dependency in CI pipeline.
112
+
113
+ ## 2018-09-22 - 3.0.59 - enhancement
114
+ integrated smartlog for improved logging
115
+
116
+ - Logs now utilize smartlog for better management.
117
+
118
+ ## 2017-09-08 - 3.0.14 - analytics
119
+ added analytics features
120
+
121
+ - Enabled analytics throughout the system.
122
+
123
+ ## 2017-08-29 - 3.0.9 - docker enhancements
124
+ docker improvements and build args implementation
125
+
126
+ - Implemented working `dockerBuildArgEnvMap`.
127
+
128
+ ## 2017-07-27 - 2.4.0 - stability improvements
129
+ various updates to stabilize the environment
130
+
131
+ - Fixed npmci versioning issues.
132
+
133
+ ## 2016-11-25 - 2.3.24 - global tools
134
+ improved handling for global tool installations
135
+
136
+ - Improved install handling for needed global tools.
package/license ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Lossless GmbH
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@ship.zone/szci",
3
+ "version": "7.1.0",
4
+ "description": "Serve Zone CI - A tool to streamline Node.js and Docker workflows within CI environments, particularly GitLab CI, providing various CI/CD utilities. Powered by Deno with standalone executables.",
5
+ "keywords": [
6
+ "Node.js",
7
+ "Docker",
8
+ "GitLab CI",
9
+ "GitHub CI",
10
+ "Gitea CI",
11
+ "CI/CD",
12
+ "automation",
13
+ "npm",
14
+ "TypeScript",
15
+ "Deno",
16
+ "cloud",
17
+ "SSH",
18
+ "registry",
19
+ "container management",
20
+ "continuous integration",
21
+ "continuous deployment"
22
+ ],
23
+ "homepage": "https://code.foss.global/ship.zone/szci",
24
+ "bugs": {
25
+ "url": "https://code.foss.global/ship.zone/szci/issues"
26
+ },
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "git+https://code.foss.global/ship.zone/szci.git"
30
+ },
31
+ "author": "Lossless GmbH",
32
+ "license": "MIT",
33
+ "type": "module",
34
+ "bin": {
35
+ "szci": "./bin/szci-wrapper.js"
36
+ },
37
+ "scripts": {
38
+ "postinstall": "node scripts/install-binary.js",
39
+ "prepublishOnly": "echo 'Publishing SZCI binaries to npm...'",
40
+ "test": "echo 'Tests are run with Deno: deno task test'",
41
+ "build": "echo 'no build needed'"
42
+ },
43
+ "files": [
44
+ "bin/",
45
+ "scripts/install-binary.js",
46
+ "readme.md",
47
+ "license",
48
+ "changelog.md"
49
+ ],
50
+ "engines": {
51
+ "node": ">=14.0.0"
52
+ },
53
+ "os": [
54
+ "darwin",
55
+ "linux",
56
+ "win32"
57
+ ],
58
+ "cpu": [
59
+ "x64",
60
+ "arm64"
61
+ ],
62
+ "publishConfig": {
63
+ "access": "public",
64
+ "registry": "https://registry.npmjs.org/"
65
+ },
66
+ "packageManager": "pnpm@10.18.1+sha512.77a884a165cbba2d8d1c19e3b4880eee6d2fcabd0d879121e282196b80042351d5eb3ca0935fa599da1dc51265cc68816ad2bddd2a2de5ea9fdf92adbec7cd34"
67
+ }
@@ -0,0 +1,55 @@
1
+ - Focus on CLI usage in CI environments.
2
+ - Show GitLab CI, GitHub CI and Gitea CI examples.
3
+
4
+ ## Architecture
5
+
6
+ szci is a thin orchestrator that delegates heavy lifting to specialized tools:
7
+ - **Docker**: Delegates all operations to `@git.zone/tsdocker` via `npx`
8
+ - **NPM**: Thin wrapper around `pnpm` with .npmrc generation from `SZCI_TOKEN_NPM*` env vars
9
+ - **Node.js**: NVM-based version management (stable=22, lts=20, legacy=18)
10
+ - **SSH**: Deploys SSH keys from `SZCI_SSHKEY_*` env vars
11
+ - **Git**: GitHub mirroring via `SZCI_GIT_GITHUBTOKEN`
12
+ - **Cloudly**: Integration with serve.zone infrastructure
13
+
14
+ ## Docker Env Var Bridging
15
+
16
+ szci bridges its own env var format to tsdocker's format before delegation:
17
+ - `SZCI_LOGIN_DOCKER*` -> `DOCKER_REGISTRY_N` (pipe-delimited: `url|user|pass`)
18
+ - GitLab CI: `CI_JOB_TOKEN` -> `DOCKER_REGISTRY_0` for `registry.gitlab.com`
19
+
20
+ ## Deno Migration Status
21
+
22
+ The project has been fully migrated from Node.js to Deno runtime.
23
+
24
+ ### Environment Variables
25
+
26
+ All environment variables have been rebranded from NPMCI_* to SZCI_*:
27
+
28
+ | Old Name | New Name |
29
+ |----------|----------|
30
+ | `NPMCI_COMPUTED_REPOURL` | `SZCI_COMPUTED_REPOURL` |
31
+ | `NPMCI_URL_CLOUDLY` | `SZCI_URL_CLOUDLY` |
32
+ | `NPMCI_GIT_GITHUBTOKEN` | `SZCI_GIT_GITHUBTOKEN` |
33
+ | `NPMCI_GIT_GITHUBGROUP` | `SZCI_GIT_GITHUBGROUP` |
34
+ | `NPMCI_GIT_GITHUB` | `SZCI_GIT_GITHUB` |
35
+ | `NPMCI_SSHKEY_*` | `SZCI_SSHKEY_*` |
36
+ | `NPMCI_LOGIN_DOCKER*` | `SZCI_LOGIN_DOCKER*` |
37
+ | `NPMCI_TOKEN_NPM*` | `SZCI_TOKEN_NPM*` |
38
+ | `NPMTS_TEST` | `SZCI_TEST` |
39
+ | `DEBUG_NPMCI` | `DEBUG_SZCI` |
40
+
41
+ ### Runtime
42
+
43
+ - Uses Deno APIs (`Deno.env`, `Deno.cwd`, `Deno.exit`)
44
+ - Logger runtime set to 'deno'
45
+ - Dynamic imports use `.ts` extensions
46
+
47
+ ## Removed Modules (v7+)
48
+
49
+ The following were removed as dead/obsolete code:
50
+ - `mod_trigger` - Deprecated GitLab API v3
51
+ - `mod_precheck` - GitLab-specific runner tag validation
52
+ - `manager.cloudron` - Niche Cloudron deployment
53
+ - `mod_command` - Trivial bash wrapper
54
+ - `mod_clean` - Trivial config cleanup
55
+ - Docker manager internals (Dockerfile, DockerRegistry, RegistryStorage classes) - replaced by tsdocker delegation
package/readme.md ADDED
@@ -0,0 +1,391 @@
1
+ # @ship.zone/szci
2
+
3
+ A lightweight CI/CD orchestrator built with Deno that unifies Node.js, Docker, NPM, SSH, and Git workflows into a single CLI. Compiles to standalone binaries — no runtime required.
4
+
5
+ ## Issue Reporting and Security
6
+
7
+ For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
8
+
9
+ ## 🏗️ Architecture
10
+
11
+ szci is a **thin orchestrator** — it doesn't reinvent the wheel. Instead, it wires up best-in-class tools and handles the CI-specific glue:
12
+
13
+ | Domain | What szci does | Delegates to |
14
+ |--------|---------------|-------------|
15
+ | 🐳 Docker | Bridges `SZCI_LOGIN_DOCKER*` env vars, auto-detects GitLab CI tokens | [`@git.zone/tsdocker`](https://code.foss.global/git.zone/tsdocker) |
16
+ | 📦 NPM | Generates `.npmrc` from `SZCI_TOKEN_NPM*` env vars, handles multi-registry publish | `pnpm` + `npm publish` |
17
+ | 🟢 Node.js | Manages Node versions via NVM with named aliases | `nvm` |
18
+ | 🔑 SSH | Deploys SSH keys from env vars to `~/.ssh` | `@push.rocks/smartssh` |
19
+ | 🔀 Git | Mirrors repos to GitHub | `git remote` |
20
+
21
+ ```
22
+ CLI Input (Deno.args)
23
+
24
+ SmartCLI Router
25
+
26
+ ├─ szci docker * → env var bridging → npx @git.zone/tsdocker
27
+ ├─ szci npm * → .npmrc generation → pnpm / npm publish
28
+ ├─ szci node * → version aliasing → nvm install
29
+ ├─ szci git * → token injection → git push --mirror
30
+ └─ szci ssh * → key parsing → write to ~/.ssh
31
+ ```
32
+
33
+ ## 📥 Installation
34
+
35
+ ### Automated Installer (Recommended)
36
+
37
+ The easiest way to install szci is using the automated installer script. It handles platform detection, binary download, and global setup:
38
+
39
+ ```sh
40
+ curl -sSL https://code.foss.global/ship.zone/szci/raw/branch/main/install.sh | sudo bash
41
+ ```
42
+
43
+ To install a specific version:
44
+
45
+ ```sh
46
+ curl -sSL https://code.foss.global/ship.zone/szci/raw/branch/main/install.sh | sudo bash -s -- --version v7.0.0
47
+ ```
48
+
49
+ ### Via NPM (downloads pre-compiled binary)
50
+
51
+ ```sh
52
+ npm install -g @ship.zone/szci
53
+ ```
54
+
55
+ ### From Source
56
+
57
+ ```sh
58
+ git clone https://code.foss.global/ship.zone/szci.git
59
+ cd szci
60
+ deno task compile
61
+ ```
62
+
63
+ The compiled binaries land in `dist/binaries/` for Linux (x64/arm64), macOS (x64/arm64), and Windows (x64).
64
+
65
+ ## 🚀 Quick Start
66
+
67
+ ```sh
68
+ # Setup Node.js environment
69
+ szci node install stable
70
+
71
+ # Install project dependencies
72
+ szci npm install
73
+
74
+ # Build & push Docker images
75
+ szci docker build
76
+ szci docker push registry.example.com
77
+
78
+ # Run tests
79
+ szci npm test
80
+ ```
81
+
82
+ ## 📖 CLI Reference
83
+
84
+ ### `szci docker` — Docker Operations
85
+
86
+ All Docker commands delegate to `@git.zone/tsdocker` after bridging environment variables.
87
+
88
+ ```sh
89
+ szci docker build # Build all Dockerfiles in cwd
90
+ szci docker login # Login to all configured registries
91
+ szci docker prepare # Alias for login
92
+ szci docker push registry.example.com # Push images to a registry
93
+ szci docker pull registry.example.com # Pull images from a registry
94
+ szci docker test # Test Dockerfiles
95
+ ```
96
+
97
+ **Env var bridging:** Before delegating, szci converts its own env var format to tsdocker's expected format:
98
+
99
+ ```
100
+ SZCI_LOGIN_DOCKER_1 → DOCKER_REGISTRY_1
101
+ SZCI_LOGIN_DOCKER_2 → DOCKER_REGISTRY_2
102
+ ...
103
+ ```
104
+
105
+ In GitLab CI, `CI_JOB_TOKEN` is automatically bridged as `DOCKER_REGISTRY_0` for `registry.gitlab.com`.
106
+
107
+ ### `szci npm` — NPM/pnpm Workflows
108
+
109
+ ```sh
110
+ szci npm install # Runs pnpm install
111
+ szci npm build # Runs pnpm run build
112
+ szci npm test # Runs pnpm test
113
+ szci npm prepare # Generates ~/.npmrc from SZCI_TOKEN_NPM* env vars
114
+ szci npm publish # Full workflow: prepare → install → build → clean → npm publish
115
+ ```
116
+
117
+ The `publish` command supports multi-registry publishing. If `npmAccessLevel` is `public` and a Verdaccio registry is configured, it publishes to both npm and Verdaccio automatically.
118
+
119
+ ### `szci node` — Node.js Version Management
120
+
121
+ ```sh
122
+ szci node install stable # Node.js 22
123
+ szci node install lts # Node.js 20
124
+ szci node install legacy # Node.js 18
125
+ szci node install 21 # Any specific version
126
+ ```
127
+
128
+ Uses NVM under the hood (auto-detected at `/usr/local/nvm/nvm.sh` or `~/.nvm/nvm.sh`). After installing, it:
129
+ 1. Sets the installed version as `nvm alias default`
130
+ 2. Upgrades npm to latest
131
+ 3. Installs any global tools listed in `npmextra.json` → `npmGlobalTools`
132
+
133
+ ### `szci ssh` — SSH Key Deployment
134
+
135
+ ```sh
136
+ szci ssh prepare # Deploy SSH keys from env vars to ~/.ssh
137
+ ```
138
+
139
+ Reads all `SZCI_SSHKEY_*` env vars and writes the keys to disk.
140
+
141
+ ### `szci git` — Git Mirroring
142
+
143
+ ```sh
144
+ szci git mirror # Mirror repository to GitHub
145
+ ```
146
+
147
+ Pushes all branches and tags to a GitHub mirror. Requires `SZCI_GIT_GITHUBTOKEN`. Refuses to mirror packages marked as `private` in `package.json`.
148
+
149
+ ## ⚙️ Configuration
150
+
151
+ ### `npmextra.json`
152
+
153
+ Place this in your project root to configure szci behavior:
154
+
155
+ ```json
156
+ {
157
+ "@ship.zone/szci": {
158
+ "npmGlobalTools": ["typescript", "pnpm"],
159
+ "npmAccessLevel": "public",
160
+ "npmRegistryUrl": "registry.npmjs.org",
161
+ "urlCloudly": "https://cloudly.example.com"
162
+ }
163
+ }
164
+ ```
165
+
166
+ | Option | Type | Default | Description |
167
+ |--------|------|---------|-------------|
168
+ | `npmGlobalTools` | `string[]` | `[]` | Global npm packages to install during `node install` |
169
+ | `npmAccessLevel` | `"public" \| "private"` | `"private"` | Access level for `npm publish` |
170
+ | `npmRegistryUrl` | `string` | `"registry.npmjs.org"` | Default npm registry |
171
+ | `urlCloudly` | `string?` | — | Cloudly endpoint URL (can also be set via `SZCI_URL_CLOUDLY`) |
172
+
173
+ ## 🔐 Environment Variables
174
+
175
+ ### Docker Registry Authentication
176
+
177
+ Pipe-delimited format: `registry|username|password`
178
+
179
+ ```sh
180
+ SZCI_LOGIN_DOCKER_1="registry.example.com|myuser|mypass"
181
+ SZCI_LOGIN_DOCKER_2="ghcr.io|token|ghp_xxxx"
182
+ ```
183
+
184
+ In **GitLab CI**, the `CI_JOB_TOKEN` is automatically used for `registry.gitlab.com` — no manual config needed.
185
+
186
+ ### NPM Registry Authentication
187
+
188
+ Pipe-delimited format: `registry|token[|plain]`
189
+
190
+ ```sh
191
+ # Base64-encoded token (default)
192
+ SZCI_TOKEN_NPM_1="registry.npmjs.org|dGhlLXRva2VuLWhlcmU="
193
+
194
+ # Plain text token
195
+ SZCI_TOKEN_NPM_2="verdaccio.example.com|the-token-here|plain"
196
+ ```
197
+
198
+ ### SSH Keys
199
+
200
+ Pipe-delimited format: `host|privKeyBase64|pubKeyBase64`
201
+
202
+ ```sh
203
+ SZCI_SSHKEY_1="github.com|BASE64_PRIVATE_KEY|BASE64_PUBLIC_KEY"
204
+ SZCI_SSHKEY_2="gitlab.com|BASE64_PRIVATE_KEY|##" # Use ## to skip a field
205
+ ```
206
+
207
+ ### Git Mirroring
208
+
209
+ ```sh
210
+ SZCI_GIT_GITHUBTOKEN="ghp_your_personal_access_token"
211
+ SZCI_GIT_GITHUBGROUP="your-org" # Defaults to repo owner
212
+ SZCI_GIT_GITHUB="your-repo" # Defaults to repo name
213
+ ```
214
+
215
+ ### Debugging & Testing
216
+
217
+ ```sh
218
+ DEBUG_SZCI="true" # Log all shell commands before execution
219
+ SZCI_TEST="true" # Test mode: mocks bash execution, skips SSH disk writes
220
+ ```
221
+
222
+ ### Full Environment Variable Reference
223
+
224
+ | Variable | Purpose |
225
+ |----------|---------|
226
+ | `SZCI_LOGIN_DOCKER_*` | Docker registry credentials (pipe-delimited) |
227
+ | `SZCI_TOKEN_NPM_*` | NPM registry auth tokens (pipe-delimited) |
228
+ | `SZCI_SSHKEY_*` | SSH key pairs (pipe-delimited) |
229
+ | `SZCI_GIT_GITHUBTOKEN` | GitHub personal access token for mirroring |
230
+ | `SZCI_GIT_GITHUBGROUP` | GitHub org/user for mirror target |
231
+ | `SZCI_GIT_GITHUB` | GitHub repo name for mirror target |
232
+ | `SZCI_URL_CLOUDLY` | Cloudly endpoint URL |
233
+ | `SZCI_COMPUTED_REPOURL` | Override auto-detected repo URL |
234
+ | `DEBUG_SZCI` | Enable verbose shell command logging |
235
+ | `SZCI_TEST` | Enable test mode (mock execution) |
236
+
237
+ ## 🔄 CI/CD Integration Examples
238
+
239
+ ### GitLab CI
240
+
241
+ ```yaml
242
+ image: node:22
243
+
244
+ stages:
245
+ - prepare
246
+ - build
247
+ - test
248
+ - deploy
249
+
250
+ before_script:
251
+ - curl -sSL https://code.foss.global/ship.zone/szci/raw/branch/main/install.sh | bash
252
+
253
+ prepare:
254
+ stage: prepare
255
+ script:
256
+ - szci node install stable
257
+ - szci npm install
258
+
259
+ build:
260
+ stage: build
261
+ script:
262
+ - szci docker build
263
+
264
+ test:
265
+ stage: test
266
+ script:
267
+ - szci npm test
268
+
269
+ deploy:
270
+ stage: deploy
271
+ script:
272
+ - szci docker push $CI_REGISTRY
273
+ only:
274
+ - master
275
+ ```
276
+
277
+ > 💡 In GitLab CI, `CI_JOB_TOKEN` is automatically detected — szci will login to `registry.gitlab.com` without any extra config.
278
+
279
+ ### GitHub Actions
280
+
281
+ ```yaml
282
+ name: CI/CD
283
+
284
+ on:
285
+ push:
286
+ branches: [main]
287
+
288
+ jobs:
289
+ build:
290
+ runs-on: ubuntu-latest
291
+ steps:
292
+ - uses: actions/checkout@v4
293
+
294
+ - name: Install szci
295
+ run: curl -sSL https://code.foss.global/ship.zone/szci/raw/branch/main/install.sh | sudo bash
296
+
297
+ - name: Setup Node.js
298
+ run: szci node install stable
299
+
300
+ - name: Install & Build
301
+ run: |
302
+ szci npm install
303
+ szci npm build
304
+
305
+ - name: Test
306
+ run: szci npm test
307
+
308
+ - name: Push Docker
309
+ if: github.ref == 'refs/heads/main'
310
+ run: szci docker push ghcr.io
311
+ env:
312
+ SZCI_LOGIN_DOCKER_1: "ghcr.io|${{ github.actor }}|${{ secrets.GITHUB_TOKEN }}"
313
+ ```
314
+
315
+ ### Gitea CI (Woodpecker)
316
+
317
+ ```yaml
318
+ steps:
319
+ - name: ci
320
+ image: node:22
321
+ commands:
322
+ - curl -sSL https://code.foss.global/ship.zone/szci/raw/branch/main/install.sh | bash
323
+ - szci node install stable
324
+ - szci npm install
325
+ - szci docker build
326
+ - szci npm test
327
+ ```
328
+
329
+ ## 🔄 Migration from npmci
330
+
331
+ Upgrading from `@ship.zone/npmci`? Three steps:
332
+
333
+ 1. **Rename the binary** — replace `npmci` with `szci` in all CI scripts
334
+ 2. **Rename env vars** — `NPMCI_*` → `SZCI_*` (same formats, just the prefix changed)
335
+ 3. **Docker ops** — now delegate to `@git.zone/tsdocker` (installed automatically via `npx`)
336
+
337
+ | Old | New |
338
+ |-----|-----|
339
+ | `NPMCI_LOGIN_DOCKER*` | `SZCI_LOGIN_DOCKER*` |
340
+ | `NPMCI_TOKEN_NPM*` | `SZCI_TOKEN_NPM*` |
341
+ | `NPMCI_SSHKEY_*` | `SZCI_SSHKEY_*` |
342
+ | `NPMCI_GIT_GITHUBTOKEN` | `SZCI_GIT_GITHUBTOKEN` |
343
+ | `NPMCI_URL_CLOUDLY` | `SZCI_URL_CLOUDLY` |
344
+ | `DEBUG_NPMCI` | `DEBUG_SZCI` |
345
+ | `NPMTS_TEST` | `SZCI_TEST` |
346
+
347
+ ## 🛠️ Development
348
+
349
+ ```sh
350
+ # Type check
351
+ deno task check
352
+
353
+ # Run tests
354
+ deno task test
355
+
356
+ # Watch tests
357
+ deno task test:watch
358
+
359
+ # Dev mode
360
+ deno task dev -- --help
361
+
362
+ # Compile binaries for all platforms
363
+ deno task compile
364
+
365
+ # Format code
366
+ deno task fmt
367
+
368
+ # Lint
369
+ deno task lint
370
+ ```
371
+
372
+ ## License and Legal Information
373
+
374
+ This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./LICENSE) file.
375
+
376
+ **Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
377
+
378
+ ### Trademarks
379
+
380
+ This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
381
+
382
+ Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
383
+
384
+ ### Company Information
385
+
386
+ Task Venture Capital GmbH
387
+ Registered at District Court Bremen HRB 35230 HB, Germany
388
+
389
+ For any legal inquiries or further information, please contact us via email at hello@task.vc.
390
+
391
+ By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
@@ -0,0 +1,228 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * SZCI npm postinstall script
5
+ * Downloads the appropriate binary for the current platform from repository releases
6
+ */
7
+
8
+ import { platform, arch } from 'os';
9
+ import { existsSync, mkdirSync, writeFileSync, chmodSync, unlinkSync } from 'fs';
10
+ import { join, dirname } from 'path';
11
+ import { fileURLToPath } from 'url';
12
+ import https from 'https';
13
+ import { pipeline } from 'stream';
14
+ import { promisify } from 'util';
15
+ import { createWriteStream } from 'fs';
16
+
17
+ const __filename = fileURLToPath(import.meta.url);
18
+ const __dirname = dirname(__filename);
19
+ const streamPipeline = promisify(pipeline);
20
+
21
+ // Configuration
22
+ const REPO_BASE = 'https://code.foss.global/ship.zone/szci';
23
+ const VERSION = process.env.npm_package_version || '4.1.37';
24
+
25
+ function getBinaryInfo() {
26
+ const plat = platform();
27
+ const architecture = arch();
28
+
29
+ const platformMap = {
30
+ 'darwin': 'macos',
31
+ 'linux': 'linux',
32
+ 'win32': 'windows'
33
+ };
34
+
35
+ const archMap = {
36
+ 'x64': 'x64',
37
+ 'arm64': 'arm64'
38
+ };
39
+
40
+ const mappedPlatform = platformMap[plat];
41
+ const mappedArch = archMap[architecture];
42
+
43
+ if (!mappedPlatform || !mappedArch) {
44
+ return { supported: false, platform: plat, arch: architecture };
45
+ }
46
+
47
+ let binaryName = `szci-${mappedPlatform}-${mappedArch}`;
48
+ if (plat === 'win32') {
49
+ binaryName += '.exe';
50
+ }
51
+
52
+ return {
53
+ supported: true,
54
+ platform: mappedPlatform,
55
+ arch: mappedArch,
56
+ binaryName,
57
+ originalPlatform: plat
58
+ };
59
+ }
60
+
61
+ function downloadFile(url, destination) {
62
+ return new Promise((resolve, reject) => {
63
+ console.log(`Downloading from: ${url}`);
64
+
65
+ // Follow redirects
66
+ const download = (url, redirectCount = 0) => {
67
+ if (redirectCount > 5) {
68
+ reject(new Error('Too many redirects'));
69
+ return;
70
+ }
71
+
72
+ https.get(url, (response) => {
73
+ if (response.statusCode === 301 || response.statusCode === 302) {
74
+ console.log(`Following redirect to: ${response.headers.location}`);
75
+ download(response.headers.location, redirectCount + 1);
76
+ return;
77
+ }
78
+
79
+ if (response.statusCode !== 200) {
80
+ reject(new Error(`Failed to download: ${response.statusCode} ${response.statusMessage}`));
81
+ return;
82
+ }
83
+
84
+ const totalSize = parseInt(response.headers['content-length'], 10);
85
+ let downloadedSize = 0;
86
+ let lastProgress = 0;
87
+
88
+ response.on('data', (chunk) => {
89
+ downloadedSize += chunk.length;
90
+ const progress = Math.round((downloadedSize / totalSize) * 100);
91
+
92
+ // Only log every 10% to reduce noise
93
+ if (progress >= lastProgress + 10) {
94
+ console.log(`Download progress: ${progress}%`);
95
+ lastProgress = progress;
96
+ }
97
+ });
98
+
99
+ const file = createWriteStream(destination);
100
+
101
+ pipeline(response, file, (err) => {
102
+ if (err) {
103
+ reject(err);
104
+ } else {
105
+ console.log('Download complete!');
106
+ resolve();
107
+ }
108
+ });
109
+ }).on('error', reject);
110
+ };
111
+
112
+ download(url);
113
+ });
114
+ }
115
+
116
+ async function main() {
117
+ console.log('===========================================');
118
+ console.log(' SZCI - Binary Installation');
119
+ console.log('===========================================');
120
+ console.log('');
121
+
122
+ const binaryInfo = getBinaryInfo();
123
+
124
+ if (!binaryInfo.supported) {
125
+ console.error(`❌ Error: Unsupported platform/architecture: ${binaryInfo.platform}/${binaryInfo.arch}`);
126
+ console.error('');
127
+ console.error('Supported platforms:');
128
+ console.error(' • Linux (x64, arm64)');
129
+ console.error(' • macOS (x64, arm64)');
130
+ console.error(' • Windows (x64)');
131
+ console.error('');
132
+ console.error('If you believe your platform should be supported, please file an issue:');
133
+ console.error(' https://code.foss.global/ship.zone/szci/issues');
134
+ process.exit(1);
135
+ }
136
+
137
+ console.log(`Platform: ${binaryInfo.platform} (${binaryInfo.originalPlatform})`);
138
+ console.log(`Architecture: ${binaryInfo.arch}`);
139
+ console.log(`Binary: ${binaryInfo.binaryName}`);
140
+ console.log(`Version: ${VERSION}`);
141
+ console.log('');
142
+
143
+ // Create dist/binaries directory if it doesn't exist
144
+ const binariesDir = join(__dirname, '..', 'dist', 'binaries');
145
+ if (!existsSync(binariesDir)) {
146
+ console.log('Creating binaries directory...');
147
+ mkdirSync(binariesDir, { recursive: true });
148
+ }
149
+
150
+ const binaryPath = join(binariesDir, binaryInfo.binaryName);
151
+
152
+ // Check if binary already exists and skip download
153
+ if (existsSync(binaryPath)) {
154
+ console.log('✓ Binary already exists, skipping download');
155
+ } else {
156
+ // Construct download URL
157
+ // Try release URL first, fall back to raw branch if needed
158
+ const releaseUrl = `${REPO_BASE}/releases/download/v${VERSION}/${binaryInfo.binaryName}`;
159
+ const fallbackUrl = `${REPO_BASE}/raw/branch/master/dist/binaries/${binaryInfo.binaryName}`;
160
+
161
+ console.log('Downloading platform-specific binary...');
162
+ console.log('This may take a moment depending on your connection speed.');
163
+ console.log('');
164
+
165
+ try {
166
+ // Try downloading from release
167
+ await downloadFile(releaseUrl, binaryPath);
168
+ } catch (err) {
169
+ console.log(`Release download failed: ${err.message}`);
170
+ console.log('Trying fallback URL...');
171
+
172
+ try {
173
+ // Try fallback URL
174
+ await downloadFile(fallbackUrl, binaryPath);
175
+ } catch (fallbackErr) {
176
+ console.error(`❌ Error: Failed to download binary`);
177
+ console.error(` Primary URL: ${releaseUrl}`);
178
+ console.error(` Fallback URL: ${fallbackUrl}`);
179
+ console.error('');
180
+ console.error('This might be because:');
181
+ console.error('1. The release has not been created yet');
182
+ console.error('2. Network connectivity issues');
183
+ console.error('3. The version specified does not exist');
184
+ console.error('');
185
+ console.error('You can try:');
186
+ console.error('1. Installing from source: https://code.foss.global/ship.zone/szci');
187
+ console.error('2. Downloading the binary manually from the releases page');
188
+ console.error('3. Building from source with: deno task compile');
189
+
190
+ // Clean up partial download
191
+ if (existsSync(binaryPath)) {
192
+ unlinkSync(binaryPath);
193
+ }
194
+
195
+ process.exit(1);
196
+ }
197
+ }
198
+
199
+ console.log(`✓ Binary downloaded successfully`);
200
+ }
201
+
202
+ // On Unix-like systems, ensure the binary is executable
203
+ if (binaryInfo.originalPlatform !== 'win32') {
204
+ try {
205
+ console.log('Setting executable permissions...');
206
+ chmodSync(binaryPath, 0o755);
207
+ console.log('✓ Binary permissions updated');
208
+ } catch (err) {
209
+ console.error(`⚠️ Warning: Could not set executable permissions: ${err.message}`);
210
+ console.error(' You may need to manually run:');
211
+ console.error(` chmod +x ${binaryPath}`);
212
+ }
213
+ }
214
+
215
+ console.log('');
216
+ console.log('✅ SZCI installation completed successfully!');
217
+ console.log('');
218
+ console.log('You can now use SZCI by running:');
219
+ console.log(' szci --help');
220
+ console.log('');
221
+ console.log('===========================================');
222
+ }
223
+
224
+ // Run the installation
225
+ main().catch(err => {
226
+ console.error(`❌ Installation failed: ${err.message}`);
227
+ process.exit(1);
228
+ });