BREAKING CHANGE(szci): Rename project from npmci to szci and migrate runtime to Deno; add compiled binaries, installer and wrapper; update imports, env handling and package metadata
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -17,4 +17,8 @@ node_modules/
|
|||||||
dist/
|
dist/
|
||||||
dist_*/
|
dist_*/
|
||||||
|
|
||||||
|
# deno
|
||||||
|
deno.lock
|
||||||
|
.deno/
|
||||||
|
|
||||||
# custom
|
# custom
|
||||||
1
.serena/.gitignore
vendored
Normal file
1
.serena/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/cache
|
||||||
71
.serena/project.yml
Normal file
71
.serena/project.yml
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
# language of the project (csharp, python, rust, java, typescript, go, cpp, or ruby)
|
||||||
|
# * For C, use cpp
|
||||||
|
# * For JavaScript, use typescript
|
||||||
|
# Special requirements:
|
||||||
|
# * csharp: Requires the presence of a .sln file in the project folder.
|
||||||
|
language: typescript
|
||||||
|
|
||||||
|
# the encoding used by text files in the project
|
||||||
|
# For a list of possible encodings, see https://docs.python.org/3.11/library/codecs.html#standard-encodings
|
||||||
|
encoding: "utf-8"
|
||||||
|
|
||||||
|
# whether to use the project's gitignore file to ignore files
|
||||||
|
# Added on 2025-04-07
|
||||||
|
ignore_all_files_in_gitignore: true
|
||||||
|
# list of additional paths to ignore
|
||||||
|
# same syntax as gitignore, so you can use * and **
|
||||||
|
# Was previously called `ignored_dirs`, please update your config if you are using that.
|
||||||
|
# Added (renamed) on 2025-04-07
|
||||||
|
ignored_paths: []
|
||||||
|
|
||||||
|
# whether the project is in read-only mode
|
||||||
|
# If set to true, all editing tools will be disabled and attempts to use them will result in an error
|
||||||
|
# Added on 2025-04-18
|
||||||
|
read_only: false
|
||||||
|
|
||||||
|
# list of tool names to exclude. We recommend not excluding any tools, see the readme for more details.
|
||||||
|
# Below is the complete list of tools for convenience.
|
||||||
|
# To make sure you have the latest list of tools, and to view their descriptions,
|
||||||
|
# execute `uv run scripts/print_tool_overview.py`.
|
||||||
|
#
|
||||||
|
# * `activate_project`: Activates a project by name.
|
||||||
|
# * `check_onboarding_performed`: Checks whether project onboarding was already performed.
|
||||||
|
# * `create_text_file`: Creates/overwrites a file in the project directory.
|
||||||
|
# * `delete_lines`: Deletes a range of lines within a file.
|
||||||
|
# * `delete_memory`: Deletes a memory from Serena's project-specific memory store.
|
||||||
|
# * `execute_shell_command`: Executes a shell command.
|
||||||
|
# * `find_referencing_code_snippets`: Finds code snippets in which the symbol at the given location is referenced.
|
||||||
|
# * `find_referencing_symbols`: Finds symbols that reference the symbol at the given location (optionally filtered by type).
|
||||||
|
# * `find_symbol`: Performs a global (or local) search for symbols with/containing a given name/substring (optionally filtered by type).
|
||||||
|
# * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes.
|
||||||
|
# * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file.
|
||||||
|
# * `initial_instructions`: Gets the initial instructions for the current project.
|
||||||
|
# Should only be used in settings where the system prompt cannot be set,
|
||||||
|
# e.g. in clients you have no control over, like Claude Desktop.
|
||||||
|
# * `insert_after_symbol`: Inserts content after the end of the definition of a given symbol.
|
||||||
|
# * `insert_at_line`: Inserts content at a given line in a file.
|
||||||
|
# * `insert_before_symbol`: Inserts content before the beginning of the definition of a given symbol.
|
||||||
|
# * `list_dir`: Lists files and directories in the given directory (optionally with recursion).
|
||||||
|
# * `list_memories`: Lists memories in Serena's project-specific memory store.
|
||||||
|
# * `onboarding`: Performs onboarding (identifying the project structure and essential tasks, e.g. for testing or building).
|
||||||
|
# * `prepare_for_new_conversation`: Provides instructions for preparing for a new conversation (in order to continue with the necessary context).
|
||||||
|
# * `read_file`: Reads a file within the project directory.
|
||||||
|
# * `read_memory`: Reads the memory with the given name from Serena's project-specific memory store.
|
||||||
|
# * `remove_project`: Removes a project from the Serena configuration.
|
||||||
|
# * `replace_lines`: Replaces a range of lines within a file with new content.
|
||||||
|
# * `replace_symbol_body`: Replaces the full definition of a symbol.
|
||||||
|
# * `restart_language_server`: Restarts the language server, may be necessary when edits not through Serena happen.
|
||||||
|
# * `search_for_pattern`: Performs a search for a pattern in the project.
|
||||||
|
# * `summarize_changes`: Provides instructions for summarizing the changes made to the codebase.
|
||||||
|
# * `switch_modes`: Activates modes by providing a list of their names
|
||||||
|
# * `think_about_collected_information`: Thinking tool for pondering the completeness of collected information.
|
||||||
|
# * `think_about_task_adherence`: Thinking tool for determining whether the agent is still on track with the current task.
|
||||||
|
# * `think_about_whether_you_are_done`: Thinking tool for determining whether the task is truly completed.
|
||||||
|
# * `write_memory`: Writes a named memory (for future reference) to Serena's project-specific memory store.
|
||||||
|
excluded_tools: []
|
||||||
|
|
||||||
|
# initial prompt for the project. It will always be given to the LLM upon activating the project
|
||||||
|
# (contrary to the memories, which are loaded on demand).
|
||||||
|
initial_prompt: ""
|
||||||
|
|
||||||
|
project_name: "npmci"
|
||||||
108
bin/szci-wrapper.js
Executable file
108
bin/szci-wrapper.js
Executable file
@@ -0,0 +1,108 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SZCI npm wrapper
|
||||||
|
* This script executes the appropriate pre-compiled binary based on the current platform
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { spawn } from 'child_process';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
import { dirname, join } from 'path';
|
||||||
|
import { existsSync } from 'fs';
|
||||||
|
import { platform, arch } from 'os';
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = dirname(__filename);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the binary name for the current platform
|
||||||
|
*/
|
||||||
|
function getBinaryName() {
|
||||||
|
const plat = platform();
|
||||||
|
const architecture = arch();
|
||||||
|
|
||||||
|
// Map Node's platform/arch to our binary naming
|
||||||
|
const platformMap = {
|
||||||
|
'darwin': 'macos',
|
||||||
|
'linux': 'linux',
|
||||||
|
'win32': 'windows'
|
||||||
|
};
|
||||||
|
|
||||||
|
const archMap = {
|
||||||
|
'x64': 'x64',
|
||||||
|
'arm64': 'arm64'
|
||||||
|
};
|
||||||
|
|
||||||
|
const mappedPlatform = platformMap[plat];
|
||||||
|
const mappedArch = archMap[architecture];
|
||||||
|
|
||||||
|
if (!mappedPlatform || !mappedArch) {
|
||||||
|
console.error(`Error: Unsupported platform/architecture: ${plat}/${architecture}`);
|
||||||
|
console.error('Supported platforms: Linux, macOS, Windows');
|
||||||
|
console.error('Supported architectures: x64, arm64');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct binary name
|
||||||
|
let binaryName = `szci-${mappedPlatform}-${mappedArch}`;
|
||||||
|
if (plat === 'win32') {
|
||||||
|
binaryName += '.exe';
|
||||||
|
}
|
||||||
|
|
||||||
|
return binaryName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the binary
|
||||||
|
*/
|
||||||
|
function executeBinary() {
|
||||||
|
const binaryName = getBinaryName();
|
||||||
|
const binaryPath = join(__dirname, '..', 'dist', 'binaries', binaryName);
|
||||||
|
|
||||||
|
// Check if binary exists
|
||||||
|
if (!existsSync(binaryPath)) {
|
||||||
|
console.error(`Error: Binary not found at ${binaryPath}`);
|
||||||
|
console.error('This might happen if:');
|
||||||
|
console.error('1. The postinstall script failed to run');
|
||||||
|
console.error('2. The platform is not supported');
|
||||||
|
console.error('3. The package was not installed correctly');
|
||||||
|
console.error('');
|
||||||
|
console.error('Try reinstalling the package:');
|
||||||
|
console.error(' npm uninstall -g @ship.zone/szci');
|
||||||
|
console.error(' npm install -g @ship.zone/szci');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spawn the binary with all arguments passed through
|
||||||
|
const child = spawn(binaryPath, process.argv.slice(2), {
|
||||||
|
stdio: 'inherit',
|
||||||
|
shell: false
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle child process events
|
||||||
|
child.on('error', (err) => {
|
||||||
|
console.error(`Error executing szci: ${err.message}`);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
child.on('exit', (code, signal) => {
|
||||||
|
if (signal) {
|
||||||
|
process.kill(process.pid, signal);
|
||||||
|
} else {
|
||||||
|
process.exit(code || 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Forward signals to child process
|
||||||
|
const signals = ['SIGINT', 'SIGTERM', 'SIGHUP'];
|
||||||
|
signals.forEach(signal => {
|
||||||
|
process.on(signal, () => {
|
||||||
|
if (!child.killed) {
|
||||||
|
child.kill(signal);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute
|
||||||
|
executeBinary();
|
||||||
12
changelog.md
12
changelog.md
@@ -1,5 +1,17 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2025-10-26 - 6.0.0 - BREAKING CHANGE(szci)
|
||||||
|
Rename project from npmci to szci and migrate runtime to Deno; add compiled binaries, installer and wrapper; update imports, env handling and package metadata
|
||||||
|
|
||||||
|
- Major rename/refactor: Npmci -> Szci across the codebase (classes, filenames, modules and exports).
|
||||||
|
- Migrate runtime to Deno: add deno.json, mod.ts entry point, use Deno.std imports and .ts module imports throughout.
|
||||||
|
- Add compilation and distribution tooling: scripts/compile-all.sh, scripts/install-binary.js, bin/szci-wrapper.js and dist/binaries layout for prebuilt executables.
|
||||||
|
- Package metadata updated: package.json renamed/rewritten for @ship.zone/szci and bumped to 5.0.0, updated publishConfig, files and scripts.
|
||||||
|
- Environment API changes: replaced process.env usages with Deno.env accessors and updated path constants (Szci paths).
|
||||||
|
- Refactored helper modules: npmci.bash -> szci.bash, updated smartshell/bash wrappers and other manager modules to Deno patterns.
|
||||||
|
- Tests and imports updated to new module paths and package layout; .gitignore updated to ignore deno artifacts.
|
||||||
|
- 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.
|
||||||
|
|
||||||
## 2024-11-17 - 4.1.37 - fix(docker)
|
## 2024-11-17 - 4.1.37 - fix(docker)
|
||||||
Enhanced base image extraction logic from Dockerfile
|
Enhanced base image extraction logic from Dockerfile
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
process.env.CLI_CALL = 'true';
|
|
||||||
import * as cliTool from './ts/index.js';
|
|
||||||
cliTool.runCli();
|
|
||||||
4
cli.js
4
cli.js
@@ -1,4 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
process.env.CLI_CALL = 'true';
|
|
||||||
const cliTool = await import('./dist_ts/index.js');
|
|
||||||
cliTool.runCli();
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
process.env.CLI_CALL = 'true';
|
|
||||||
|
|
||||||
import * as tsrun from '@git.zone/tsrun';
|
|
||||||
tsrun.runPath('./cli.child.js', import.meta.url);
|
|
||||||
67
deno.json
Normal file
67
deno.json
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
{
|
||||||
|
"name": "@ship.zone/szci",
|
||||||
|
"version": "5.0.0",
|
||||||
|
"exports": "./mod.ts",
|
||||||
|
"nodeModulesDir": "auto",
|
||||||
|
"tasks": {
|
||||||
|
"dev": "deno run --allow-all mod.ts",
|
||||||
|
"compile": "deno task compile:all",
|
||||||
|
"compile:all": "bash scripts/compile-all.sh",
|
||||||
|
"test": "deno test --allow-all test/",
|
||||||
|
"test:watch": "deno test --allow-all --watch test/",
|
||||||
|
"check": "deno check mod.ts",
|
||||||
|
"fmt": "deno fmt",
|
||||||
|
"lint": "deno lint"
|
||||||
|
},
|
||||||
|
"lint": {
|
||||||
|
"rules": {
|
||||||
|
"tags": [
|
||||||
|
"recommended"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fmt": {
|
||||||
|
"useTabs": false,
|
||||||
|
"lineWidth": 100,
|
||||||
|
"indentWidth": 2,
|
||||||
|
"semiColons": true,
|
||||||
|
"singleQuote": true
|
||||||
|
},
|
||||||
|
"compilerOptions": {
|
||||||
|
"lib": [
|
||||||
|
"deno.window"
|
||||||
|
],
|
||||||
|
"strict": true
|
||||||
|
},
|
||||||
|
"imports": {
|
||||||
|
"@std/path": "jsr:@std/path@^1.0.0",
|
||||||
|
"@std/fmt": "jsr:@std/fmt@^1.0.0",
|
||||||
|
"@std/cli": "jsr:@std/cli@^1.0.0",
|
||||||
|
"@std/assert": "jsr:@std/assert@^1.0.0",
|
||||||
|
"@api.global/typedrequest": "npm:@api.global/typedrequest@^3.1.10",
|
||||||
|
"@push.rocks/lik": "npm:@push.rocks/lik@^6.1.0",
|
||||||
|
"@push.rocks/npmextra": "npm:@push.rocks/npmextra@^5.1.2",
|
||||||
|
"@push.rocks/projectinfo": "npm:@push.rocks/projectinfo@^5.0.2",
|
||||||
|
"@push.rocks/qenv": "npm:@push.rocks/qenv@^6.0.2",
|
||||||
|
"@push.rocks/smartanalytics": "npm:@push.rocks/smartanalytics@^2.0.15",
|
||||||
|
"@push.rocks/smartcli": "npm:@push.rocks/smartcli@^4.0.11",
|
||||||
|
"@push.rocks/smartdelay": "npm:@push.rocks/smartdelay@^3.0.5",
|
||||||
|
"@push.rocks/smartenv": "npm:@push.rocks/smartenv@^5.0.5",
|
||||||
|
"@push.rocks/smartfile": "npm:@push.rocks/smartfile@^11.0.21",
|
||||||
|
"@push.rocks/smartgit": "npm:@push.rocks/smartgit@^3.1.1",
|
||||||
|
"@push.rocks/smartlog": "npm:@push.rocks/smartlog@^3.0.7",
|
||||||
|
"@push.rocks/smartlog-destination-local": "npm:@push.rocks/smartlog-destination-local@^9.0.0",
|
||||||
|
"@push.rocks/smartobject": "npm:@push.rocks/smartobject@^1.0.12",
|
||||||
|
"@push.rocks/smartpath": "npm:@push.rocks/smartpath@^5.0.11",
|
||||||
|
"@push.rocks/smartpromise": "npm:@push.rocks/smartpromise@^4.0.4",
|
||||||
|
"@push.rocks/smartrequest": "npm:@push.rocks/smartrequest@^2.0.23",
|
||||||
|
"@push.rocks/smartshell": "npm:@push.rocks/smartshell@^3.0.6",
|
||||||
|
"@push.rocks/smartsocket": "npm:@push.rocks/smartsocket@^2.0.22",
|
||||||
|
"@push.rocks/smartssh": "npm:@push.rocks/smartssh@^2.0.1",
|
||||||
|
"@push.rocks/smartstring": "npm:@push.rocks/smartstring@^4.0.8",
|
||||||
|
"@push.rocks/smartexpect": "npm:@push.rocks/smartexpect@^1.0.15",
|
||||||
|
"@serve.zone/api": "npm:@serve.zone/api@^4.3.11",
|
||||||
|
"@tsclass/tsclass": "npm:@tsclass/tsclass@^4.1.2",
|
||||||
|
"through2": "npm:through2@^4.0.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
257
install.sh
Executable file
257
install.sh
Executable file
@@ -0,0 +1,257 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# SZCI Installer Script (v5.0+)
|
||||||
|
# Downloads and installs pre-compiled SZCI binary from Gitea releases
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# Direct piped installation (recommended):
|
||||||
|
# curl -sSL https://code.foss.global/ship.zone/szci/raw/branch/master/install.sh | sudo bash
|
||||||
|
#
|
||||||
|
# With version specification:
|
||||||
|
# curl -sSL https://code.foss.global/ship.zone/szci/raw/branch/master/install.sh | sudo bash -s -- --version v5.0.0
|
||||||
|
#
|
||||||
|
# Options:
|
||||||
|
# -h, --help Show this help message
|
||||||
|
# --version VERSION Install specific version (e.g., v5.0.0)
|
||||||
|
# --install-dir DIR Installation directory (default: /opt/szci)
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Default values
|
||||||
|
SHOW_HELP=0
|
||||||
|
SPECIFIED_VERSION=""
|
||||||
|
INSTALL_DIR="/opt/szci"
|
||||||
|
GITEA_BASE_URL="https://code.foss.global"
|
||||||
|
GITEA_REPO="ship.zone/szci"
|
||||||
|
|
||||||
|
# Parse command line arguments
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
-h|--help)
|
||||||
|
SHOW_HELP=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--version)
|
||||||
|
SPECIFIED_VERSION="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--install-dir)
|
||||||
|
INSTALL_DIR="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1"
|
||||||
|
echo "Use -h or --help for usage information"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $SHOW_HELP -eq 1 ]; then
|
||||||
|
echo "SZCI Installer Script (v5.0+)"
|
||||||
|
echo "Downloads and installs pre-compiled SZCI binary"
|
||||||
|
echo ""
|
||||||
|
echo "Usage: $0 [options]"
|
||||||
|
echo ""
|
||||||
|
echo "Options:"
|
||||||
|
echo " -h, --help Show this help message"
|
||||||
|
echo " --version VERSION Install specific version (e.g., v5.0.0)"
|
||||||
|
echo " --install-dir DIR Installation directory (default: /opt/szci)"
|
||||||
|
echo ""
|
||||||
|
echo "Examples:"
|
||||||
|
echo " # Install latest version"
|
||||||
|
echo " curl -sSL https://code.foss.global/ship.zone/szci/raw/branch/master/install.sh | sudo bash"
|
||||||
|
echo ""
|
||||||
|
echo " # Install specific version"
|
||||||
|
echo " curl -sSL https://code.foss.global/ship.zone/szci/raw/branch/master/install.sh | sudo bash -s -- --version v5.0.0"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo "Please run as root (sudo bash install.sh or pipe to sudo bash)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Helper function to detect OS and architecture
|
||||||
|
detect_platform() {
|
||||||
|
local os=$(uname -s)
|
||||||
|
local arch=$(uname -m)
|
||||||
|
|
||||||
|
# Map OS
|
||||||
|
case "$os" in
|
||||||
|
Linux)
|
||||||
|
os_name="linux"
|
||||||
|
;;
|
||||||
|
Darwin)
|
||||||
|
os_name="macos"
|
||||||
|
;;
|
||||||
|
MINGW*|MSYS*|CYGWIN*)
|
||||||
|
os_name="windows"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Error: Unsupported operating system: $os"
|
||||||
|
echo "Supported: Linux, macOS, Windows"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Map architecture
|
||||||
|
case "$arch" in
|
||||||
|
x86_64|amd64)
|
||||||
|
arch_name="x64"
|
||||||
|
;;
|
||||||
|
aarch64|arm64)
|
||||||
|
arch_name="arm64"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Error: Unsupported architecture: $arch"
|
||||||
|
echo "Supported: x86_64/amd64 (x64), aarch64/arm64 (arm64)"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Construct binary name
|
||||||
|
if [ "$os_name" = "windows" ]; then
|
||||||
|
echo "szci-${os_name}-${arch_name}.exe"
|
||||||
|
else
|
||||||
|
echo "szci-${os_name}-${arch_name}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get latest release version from Gitea API
|
||||||
|
get_latest_version() {
|
||||||
|
echo "Fetching latest release version from Gitea..." >&2
|
||||||
|
|
||||||
|
local api_url="${GITEA_BASE_URL}/api/v1/repos/${GITEA_REPO}/releases/latest"
|
||||||
|
local response=$(curl -sSL "$api_url" 2>/dev/null)
|
||||||
|
|
||||||
|
if [ $? -ne 0 ] || [ -z "$response" ]; then
|
||||||
|
echo "Error: Failed to fetch latest release information from Gitea API" >&2
|
||||||
|
echo "URL: $api_url" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extract tag_name from JSON response
|
||||||
|
local version=$(echo "$response" | grep -o '"tag_name":"[^"]*"' | cut -d'"' -f4)
|
||||||
|
|
||||||
|
if [ -z "$version" ]; then
|
||||||
|
echo "Error: Could not determine latest version from API response" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$version"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main installation process
|
||||||
|
echo "================================================"
|
||||||
|
echo " SZCI Installation Script (v5.0+)"
|
||||||
|
echo " Serve Zone CI/CD Tool"
|
||||||
|
echo "================================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Detect platform
|
||||||
|
BINARY_NAME=$(detect_platform)
|
||||||
|
echo "Detected platform: $BINARY_NAME"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Determine version to install
|
||||||
|
if [ -n "$SPECIFIED_VERSION" ]; then
|
||||||
|
VERSION="$SPECIFIED_VERSION"
|
||||||
|
echo "Installing specified version: $VERSION"
|
||||||
|
else
|
||||||
|
VERSION=$(get_latest_version)
|
||||||
|
echo "Installing latest version: $VERSION"
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Construct download URL
|
||||||
|
DOWNLOAD_URL="${GITEA_BASE_URL}/${GITEA_REPO}/releases/download/${VERSION}/${BINARY_NAME}"
|
||||||
|
echo "Download URL: $DOWNLOAD_URL"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Clean installation directory - ensure only binary exists
|
||||||
|
if [ -d "$INSTALL_DIR" ]; then
|
||||||
|
echo "Cleaning installation directory: $INSTALL_DIR"
|
||||||
|
rm -rf "$INSTALL_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create fresh installation directory
|
||||||
|
echo "Creating installation directory: $INSTALL_DIR"
|
||||||
|
mkdir -p "$INSTALL_DIR"
|
||||||
|
|
||||||
|
# Download binary
|
||||||
|
echo "Downloading SZCI binary..."
|
||||||
|
TEMP_FILE="$INSTALL_DIR/szci.download"
|
||||||
|
curl -sSL "$DOWNLOAD_URL" -o "$TEMP_FILE"
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "Error: Failed to download binary from $DOWNLOAD_URL"
|
||||||
|
echo ""
|
||||||
|
echo "Please check:"
|
||||||
|
echo " 1. Your internet connection"
|
||||||
|
echo " 2. The specified version exists: ${GITEA_BASE_URL}/${GITEA_REPO}/releases"
|
||||||
|
echo " 3. The platform binary is available for this release"
|
||||||
|
rm -f "$TEMP_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if download was successful (file exists and not empty)
|
||||||
|
if [ ! -s "$TEMP_FILE" ]; then
|
||||||
|
echo "Error: Downloaded file is empty or does not exist"
|
||||||
|
rm -f "$TEMP_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Move to final location
|
||||||
|
BINARY_PATH="$INSTALL_DIR/szci"
|
||||||
|
mv "$TEMP_FILE" "$BINARY_PATH"
|
||||||
|
|
||||||
|
if [ $? -ne 0 ] || [ ! -f "$BINARY_PATH" ]; then
|
||||||
|
echo "Error: Failed to move binary to $BINARY_PATH"
|
||||||
|
rm -f "$TEMP_FILE" 2>/dev/null
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make executable
|
||||||
|
chmod +x "$BINARY_PATH"
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "Error: Failed to make binary executable"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Binary installed successfully to: $BINARY_PATH"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check if /usr/local/bin is in PATH
|
||||||
|
if [[ ":$PATH:" == *":/usr/local/bin:"* ]]; then
|
||||||
|
BIN_DIR="/usr/local/bin"
|
||||||
|
else
|
||||||
|
BIN_DIR="/usr/bin"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create symlink for global access
|
||||||
|
ln -sf "$BINARY_PATH" "$BIN_DIR/szci"
|
||||||
|
echo "Symlink created: $BIN_DIR/szci -> $BINARY_PATH"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "================================================"
|
||||||
|
echo " SZCI Installation Complete!"
|
||||||
|
echo "================================================"
|
||||||
|
echo ""
|
||||||
|
echo "Installation details:"
|
||||||
|
echo " Binary location: $BINARY_PATH"
|
||||||
|
echo " Symlink location: $BIN_DIR/szci"
|
||||||
|
echo " Version: $VERSION"
|
||||||
|
echo ""
|
||||||
|
echo "Get started:"
|
||||||
|
echo " szci --version"
|
||||||
|
echo " szci --help"
|
||||||
|
echo " szci node install stable # Install Node.js"
|
||||||
|
echo " szci docker build # Build Docker images"
|
||||||
|
echo " szci npm test # Run tests"
|
||||||
|
echo ""
|
||||||
|
echo "For CI/CD integration examples, visit:"
|
||||||
|
echo " https://code.foss.global/ship.zone/szci"
|
||||||
|
echo ""
|
||||||
48
mod.ts
Normal file
48
mod.ts
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
#!/usr/bin/env -S deno run --allow-all
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SZCI - Serve Zone CI/CD Tool
|
||||||
|
*
|
||||||
|
* A command-line tool for streamlining Node.js and Docker workflows
|
||||||
|
* within CI environments, particularly GitLab CI, GitHub CI, and Gitea CI.
|
||||||
|
*
|
||||||
|
* Required Permissions:
|
||||||
|
* - --allow-net: Network access for Docker registries, npm, git operations
|
||||||
|
* - --allow-read: Read configuration files, Dockerfiles, package.json
|
||||||
|
* - --allow-write: Write configuration files, build artifacts
|
||||||
|
* - --allow-run: Execute system commands (docker, git, npm, ssh)
|
||||||
|
* - --allow-sys: Access system information (OS details)
|
||||||
|
* - --allow-env: Read/write environment variables
|
||||||
|
*
|
||||||
|
* @module
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Szci } from './ts/szci.classes.szci.ts';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main entry point for the SZCI application
|
||||||
|
* Parses command-line arguments and executes the requested command
|
||||||
|
*/
|
||||||
|
async function main(): Promise<void> {
|
||||||
|
// Create Szci instance
|
||||||
|
const szciInstance = new Szci();
|
||||||
|
|
||||||
|
// Start the CLI
|
||||||
|
// Deno.args is already 0-indexed (unlike Node's process.argv which starts at index 2)
|
||||||
|
// The smartcli library may expect process.argv format, so we might need to prepend placeholders
|
||||||
|
await szciInstance.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute main and handle errors
|
||||||
|
if (import.meta.main) {
|
||||||
|
try {
|
||||||
|
await main();
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
||||||
|
Deno.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export for programmatic use
|
||||||
|
export { Szci } from './ts/szci.classes.szci.ts';
|
||||||
|
export { Dockerfile } from './ts/manager.docker/mod.classes.dockerfile.ts';
|
||||||
125
package.json
125
package.json
@@ -1,79 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@ship.zone/npmci",
|
"name": "@ship.zone/szci",
|
||||||
"version": "4.1.37",
|
"version": "5.0.0",
|
||||||
"private": false,
|
"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.",
|
||||||
"description": "A tool to streamline Node.js and Docker workflows within CI environments, particularly GitLab CI, providing various CI/CD utilities.",
|
|
||||||
"main": "dist_ts/index.js",
|
|
||||||
"typings": "dist_ts/index.d.ts",
|
|
||||||
"type": "module",
|
|
||||||
"bin": {
|
|
||||||
"npmci": "cli.js"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"test": "tstest test/",
|
|
||||||
"build": "tsbuild --allowimplicitany && (npm run testVersion)",
|
|
||||||
"testVersion": "(cd test/assets/ && node ../../cli.js -v)",
|
|
||||||
"buildDocs": "tsdoc"
|
|
||||||
},
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "git+ssh://git@gitlab.com/gitzone/npmci.git"
|
|
||||||
},
|
|
||||||
"author": "Lossless GmbH",
|
|
||||||
"license": "MIT",
|
|
||||||
"bugs": {
|
|
||||||
"url": "https://gitlab.com/gitzone/npmci/issues"
|
|
||||||
},
|
|
||||||
"homepage": "https://gitlab.com/gitzone/npmci#README",
|
|
||||||
"devDependencies": {
|
|
||||||
"@git.zone/tsbuild": "^2.2.0",
|
|
||||||
"@git.zone/tsrun": "^1.3.3",
|
|
||||||
"@git.zone/tstest": "^1.0.77",
|
|
||||||
"@push.rocks/tapbundle": "^5.5.0",
|
|
||||||
"@types/node": "^22.9.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@api.global/typedrequest": "^3.1.10",
|
|
||||||
"@push.rocks/lik": "^6.1.0",
|
|
||||||
"@push.rocks/npmextra": "^5.1.2",
|
|
||||||
"@push.rocks/projectinfo": "^5.0.2",
|
|
||||||
"@push.rocks/qenv": "^6.0.2",
|
|
||||||
"@push.rocks/smartanalytics": "^2.0.15",
|
|
||||||
"@push.rocks/smartcli": "^4.0.11",
|
|
||||||
"@push.rocks/smartdelay": "^3.0.5",
|
|
||||||
"@push.rocks/smartenv": "^5.0.5",
|
|
||||||
"@push.rocks/smartfile": "^11.0.21",
|
|
||||||
"@push.rocks/smartgit": "^3.1.1",
|
|
||||||
"@push.rocks/smartlog": "^3.0.7",
|
|
||||||
"@push.rocks/smartlog-destination-local": "^9.0.0",
|
|
||||||
"@push.rocks/smartobject": "^1.0.12",
|
|
||||||
"@push.rocks/smartpath": "^5.0.11",
|
|
||||||
"@push.rocks/smartpromise": "^4.0.4",
|
|
||||||
"@push.rocks/smartrequest": "^2.0.23",
|
|
||||||
"@push.rocks/smartshell": "^3.0.6",
|
|
||||||
"@push.rocks/smartsocket": "^2.0.22",
|
|
||||||
"@push.rocks/smartssh": "^2.0.1",
|
|
||||||
"@push.rocks/smartstring": "^4.0.8",
|
|
||||||
"@serve.zone/api": "^4.3.11",
|
|
||||||
"@tsclass/tsclass": "^4.1.2",
|
|
||||||
"@types/through2": "^2.0.38",
|
|
||||||
"through2": "^4.0.2"
|
|
||||||
},
|
|
||||||
"files": [
|
|
||||||
"ts/**/*",
|
|
||||||
"ts_web/**/*",
|
|
||||||
"dist/**/*",
|
|
||||||
"dist_*/**/*",
|
|
||||||
"dist_ts/**/*",
|
|
||||||
"dist_ts_web/**/*",
|
|
||||||
"assets/**/*",
|
|
||||||
"cli.js",
|
|
||||||
"npmextra.json",
|
|
||||||
"readme.md"
|
|
||||||
],
|
|
||||||
"browserslist": [
|
|
||||||
"last 1 chrome versions"
|
|
||||||
],
|
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"Node.js",
|
"Node.js",
|
||||||
"Docker",
|
"Docker",
|
||||||
@@ -84,11 +12,56 @@
|
|||||||
"automation",
|
"automation",
|
||||||
"npm",
|
"npm",
|
||||||
"TypeScript",
|
"TypeScript",
|
||||||
|
"Deno",
|
||||||
"cloud",
|
"cloud",
|
||||||
"SSH",
|
"SSH",
|
||||||
"registry",
|
"registry",
|
||||||
"container management",
|
"container management",
|
||||||
"continuous integration",
|
"continuous integration",
|
||||||
"continuous deployment"
|
"continuous deployment"
|
||||||
]
|
],
|
||||||
|
"homepage": "https://code.foss.global/ship.zone/szci",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://code.foss.global/ship.zone/szci/issues"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://code.foss.global/ship.zone/szci.git"
|
||||||
|
},
|
||||||
|
"author": "Lossless GmbH",
|
||||||
|
"license": "MIT",
|
||||||
|
"type": "module",
|
||||||
|
"bin": {
|
||||||
|
"szci": "./bin/szci-wrapper.js"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"postinstall": "node scripts/install-binary.js",
|
||||||
|
"prepublishOnly": "echo 'Publishing SZCI binaries to npm...'",
|
||||||
|
"test": "echo 'Tests are run with Deno: deno task test'",
|
||||||
|
"build": "echo 'no build needed'"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"bin/",
|
||||||
|
"scripts/install-binary.js",
|
||||||
|
"readme.md",
|
||||||
|
"license",
|
||||||
|
"changelog.md"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
},
|
||||||
|
"os": [
|
||||||
|
"darwin",
|
||||||
|
"linux",
|
||||||
|
"win32"
|
||||||
|
],
|
||||||
|
"cpu": [
|
||||||
|
"x64",
|
||||||
|
"arm64"
|
||||||
|
],
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public",
|
||||||
|
"registry": "https://registry.npmjs.org/"
|
||||||
|
},
|
||||||
|
"packageManager": "pnpm@10.18.1+sha512.77a884a165cbba2d8d1c19e3b4880eee6d2fcabd0d879121e282196b80042351d5eb3ca0935fa599da1dc51265cc68816ad2bddd2a2de5ea9fdf92adbec7cd34"
|
||||||
}
|
}
|
||||||
|
|||||||
4
pnpm-workspace.yaml
Normal file
4
pnpm-workspace.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
onlyBuiltDependencies:
|
||||||
|
- esbuild
|
||||||
|
- mongodb-memory-server
|
||||||
|
- puppeteer
|
||||||
682
readme.md
682
readme.md
@@ -1,30 +1,115 @@
|
|||||||
# @ship.zone/npmci
|
# @ship.zone/szci
|
||||||
A tool to enhance Node.js and Docker workflows within GitLab CI, providing various CI/CD utilities.
|
|
||||||
|
|
||||||
## Install
|
**Serve Zone CI** - A powerful CI/CD tool for streamlining Node.js and Docker workflows within CI environments (GitLab CI, GitHub CI, Gitea CI). Now powered by Deno with standalone executables.
|
||||||
|
|
||||||
To install `@ship.zone/npmci`, you can use npm or yarn:
|
## ✨ Features
|
||||||
|
|
||||||
|
- 🚀 **Standalone Executables** - No Node.js installation required
|
||||||
|
- 🐳 **Docker Integration** - Build, tag, and push Docker images
|
||||||
|
- 📦 **NPM Management** - Install, test, and publish npm packages
|
||||||
|
- 🔧 **Node.js Version Management** - Install and switch between Node versions
|
||||||
|
- 🔐 **SSH Key Management** - Deploy SSH keys from environment variables
|
||||||
|
- ☁️ **Multi-Registry Support** - Push to multiple Docker registries
|
||||||
|
- 🎯 **Cross-Platform** - Binaries for Linux, macOS, and Windows
|
||||||
|
|
||||||
|
## 📥 Installation
|
||||||
|
|
||||||
|
### NPM (Recommended)
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
# Using npm
|
npm install -g @ship.zone/szci
|
||||||
npm install @ship.zone/npmci
|
|
||||||
|
|
||||||
# Using yarn
|
|
||||||
yarn add @ship.zone/npmci
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
The package will automatically download the appropriate pre-compiled binary for your platform.
|
||||||
|
|
||||||
`npmci` is designed to streamline CI/CD processes, particularly in Docker and Node.js environments. The following sections illustrate its usage in various scenarios, from handling Node versions to building Docker images and more.
|
### From Source (Deno Required)
|
||||||
|
|
||||||
### 1. Integration with GitLab CI, GitHub CI, and Gitea CI
|
```sh
|
||||||
|
git clone https://code.foss.global/ship.zone/szci.git
|
||||||
|
cd szci
|
||||||
|
deno task compile
|
||||||
|
```
|
||||||
|
|
||||||
#### GitLab CI
|
## 🚀 Quick Start
|
||||||
|
|
||||||
An example of integrating `npmci` into a GitLab CI configuration could look like this:
|
```sh
|
||||||
|
# Install Node.js
|
||||||
|
szci node install stable
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
szci npm install
|
||||||
|
|
||||||
|
# Build Docker images
|
||||||
|
szci docker build
|
||||||
|
|
||||||
|
# Run tests
|
||||||
|
szci npm test
|
||||||
|
|
||||||
|
# Push Docker images
|
||||||
|
szci docker push registry.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📖 Usage
|
||||||
|
|
||||||
|
### Node.js Management
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Install specific Node.js version
|
||||||
|
szci node install lts
|
||||||
|
szci node install stable
|
||||||
|
szci node install 18
|
||||||
|
|
||||||
|
# Install from .nvmrc
|
||||||
|
szci node install legacy
|
||||||
|
```
|
||||||
|
|
||||||
|
### NPM Commands
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Install dependencies
|
||||||
|
szci npm install
|
||||||
|
|
||||||
|
# Run tests
|
||||||
|
szci npm test
|
||||||
|
|
||||||
|
# Publish package
|
||||||
|
szci npm publish
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker Workflows
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Prepare Docker environment
|
||||||
|
szci docker prepare
|
||||||
|
|
||||||
|
# Build all Dockerfiles
|
||||||
|
szci docker build
|
||||||
|
|
||||||
|
# Push to registry
|
||||||
|
szci docker push registry.example.com
|
||||||
|
|
||||||
|
# Pull from registry
|
||||||
|
szci docker pull registry.example.com
|
||||||
|
|
||||||
|
# Test Dockerfiles
|
||||||
|
szci docker test
|
||||||
|
```
|
||||||
|
|
||||||
|
### SSH Key Management
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Deploy SSH keys from environment
|
||||||
|
szci ssh prepare
|
||||||
|
```
|
||||||
|
|
||||||
|
Set environment variables like `NPMCI_SSHKEY_1`, `NPMCI_SSHKEY_2`, etc.
|
||||||
|
|
||||||
|
## 🔧 CI/CD Integration
|
||||||
|
|
||||||
|
### GitLab CI
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
image: hosttoday/ht-docker-node:npmci
|
image: denoland/deno:alpine
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- prepare
|
- prepare
|
||||||
@@ -32,463 +117,184 @@ stages:
|
|||||||
- test
|
- test
|
||||||
- deploy
|
- deploy
|
||||||
|
|
||||||
default:
|
variables:
|
||||||
before_script:
|
SZCI_VERSION: "latest"
|
||||||
- npmci node install stable
|
|
||||||
- npmci npm install
|
before_script:
|
||||||
|
- deno install --allow-all --global --name szci https://code.foss.global/ship.zone/szci/raw/branch/master/mod.ts
|
||||||
|
# OR use the npm package:
|
||||||
|
# - npm install -g @ship.zone/szci
|
||||||
|
|
||||||
prepare:
|
prepare:
|
||||||
stage: prepare
|
stage: prepare
|
||||||
script:
|
script:
|
||||||
- npmci prepare npm
|
- szci node install stable
|
||||||
- npmci prepare docker
|
- szci npm install
|
||||||
|
|
||||||
build:
|
build:
|
||||||
stage: build
|
stage: build
|
||||||
script:
|
script:
|
||||||
- npmci docker build
|
- szci docker build
|
||||||
|
|
||||||
test:
|
test:
|
||||||
stage: test
|
stage: test
|
||||||
script:
|
script:
|
||||||
- npmci npm test
|
- szci npm test
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
script:
|
script:
|
||||||
- npmci publish npm
|
- szci docker push $CI_REGISTRY
|
||||||
- npmci docker push
|
only:
|
||||||
|
- master
|
||||||
environment:
|
|
||||||
name: production
|
|
||||||
url: http://example.com
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### GitHub Actions
|
### GitHub Actions
|
||||||
|
|
||||||
Similarly, you can set up `npmci` in GitHub Actions:
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
name: CI Pipeline
|
name: CI Pipeline
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches: [main]
|
||||||
- main
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
prepare:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Set up Node.js
|
|
||||||
uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: '14'
|
|
||||||
- run: npm install -g @ship.zone/npmci
|
|
||||||
- run: npmci node install stable
|
|
||||||
- run: npmci npm install
|
|
||||||
|
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: prepare
|
|
||||||
steps:
|
steps:
|
||||||
- run: npmci docker build
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
test:
|
- name: Install SZCI
|
||||||
runs-on: ubuntu-latest
|
run: npm install -g @ship.zone/szci
|
||||||
needs: build
|
|
||||||
steps:
|
|
||||||
- run: npmci npm test
|
|
||||||
|
|
||||||
deploy:
|
- name: Setup Node.js
|
||||||
runs-on: ubuntu-latest
|
run: szci node install stable
|
||||||
needs: test
|
|
||||||
steps:
|
- name: Install Dependencies
|
||||||
- run: npmci publish npm
|
run: szci npm install
|
||||||
- run: npmci docker push
|
|
||||||
|
- name: Build Docker Images
|
||||||
|
run: szci docker build
|
||||||
|
|
||||||
|
- name: Run Tests
|
||||||
|
run: szci npm test
|
||||||
|
|
||||||
|
- name: Push Images
|
||||||
|
if: github.ref == 'refs/heads/main'
|
||||||
|
run: szci docker push ghcr.io
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Gitea CI
|
## ⚙️ Configuration
|
||||||
|
|
||||||
Lastly, for Gitea CI:
|
Create an `npmextra.json` file in your project root:
|
||||||
|
|
||||||
```yaml
|
```json
|
||||||
image: hosttoday/ht-docker-node:npmci
|
{
|
||||||
|
"npmci": {
|
||||||
pipelines:
|
"npmGlobalTools": [],
|
||||||
default:
|
"npmAccessLevel": "public",
|
||||||
- step:
|
"npmRegistryUrl": "registry.npmjs.org",
|
||||||
name: Prepare
|
"dockerRegistries": [
|
||||||
image: hosttoday/ht-docker-node:npmci
|
"registry.gitlab.com"
|
||||||
commands:
|
],
|
||||||
- npmci node install stable
|
"dockerRegistryRepoMap": {
|
||||||
- npmci npm install
|
"registry.gitlab.com": "mygroup/myrepo"
|
||||||
- npmci prepare npm
|
},
|
||||||
- npmci prepare docker
|
"dockerBuildargEnvMap": {
|
||||||
|
"ARG_NAME": "ENV_VAR_NAME"
|
||||||
- step:
|
}
|
||||||
name: Build
|
|
||||||
image: hosttoday/ht-docker-node:npmci
|
|
||||||
commands:
|
|
||||||
- npmci docker build
|
|
||||||
|
|
||||||
- step:
|
|
||||||
name: Test
|
|
||||||
image: hosttoday/ht-docker-node:npmci
|
|
||||||
commands:
|
|
||||||
- npmci npm test
|
|
||||||
|
|
||||||
- step:
|
|
||||||
name: Deploy
|
|
||||||
image: hosttoday/ht-docker-node:npmci
|
|
||||||
commands:
|
|
||||||
- npmci publish npm
|
|
||||||
- npmci docker push
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Handle Node Versions
|
|
||||||
|
|
||||||
One of the core features of `npmci` is managing Node versions in your CI environment. You can specify which version of Node to install:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { Npmci } from '@ship.zone/npmci';
|
|
||||||
|
|
||||||
async function manageNodeVersions() {
|
|
||||||
const npmciInstance = new Npmci();
|
|
||||||
await npmciInstance.start();
|
|
||||||
|
|
||||||
await npmciInstance.nodejsManager.handleCli({
|
|
||||||
_: ['node', 'install', 'stable'] // Installs the latest stable version
|
|
||||||
});
|
|
||||||
|
|
||||||
await npmciInstance.nodejsManager.handleCli({
|
|
||||||
_: ['node', 'install', 'lts'] // Installs the Long-Term Support (LTS) version
|
|
||||||
});
|
|
||||||
|
|
||||||
await npmciInstance.nodejsManager.handleCli({
|
|
||||||
_: ['node', 'install', 'legacy'] // Installs a legacy version
|
|
||||||
});
|
|
||||||
|
|
||||||
await npmciInstance.nodejsManager.handleCli({
|
|
||||||
_: ['node', 'install', '14.17.0'] // Install a specific version of Node
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
manageNodeVersions().then(() => console.log('Node versions managed successfully.'));
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Handling npm and Yarn Tasks
|
|
||||||
|
|
||||||
`npmci` provides numerous utilities to streamline npm and yarn workflow tasks within a CI/CD pipeline.
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { Npmci } from '@ship.zone/npmci';
|
|
||||||
|
|
||||||
async function manageNpmTasks() {
|
|
||||||
const npmciInstance = new Npmci();
|
|
||||||
await npmciInstance.start();
|
|
||||||
|
|
||||||
await npmciInstance.npmManager.handleCli({ _: ['npm', 'install'] }); // Installs dependencies
|
|
||||||
await npmciInstance.npmManager.handleCli({ _: ['npm', 'test'] }); // Runs tests
|
|
||||||
await npmciInstance.npmManager.handleCli({ _: ['npm', 'publish'] }); // Publishes the package
|
|
||||||
}
|
|
||||||
|
|
||||||
manageNpmTasks().then(() => console.log('Npm tasks handled successfully.'));
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. Docker Task Handling
|
|
||||||
|
|
||||||
`npmci` simplifies Docker operations, particularly in building, testing, and publishing Docker images.
|
|
||||||
|
|
||||||
**Prepare Docker Environment:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { Npmci } from '@ship.zone/npmci';
|
|
||||||
|
|
||||||
async function prepareDocker() {
|
|
||||||
const npmciInstance = new Npmci();
|
|
||||||
await npmciInstance.start();
|
|
||||||
|
|
||||||
await npmciInstance.dockerManager.handleCli({ _: ['docker', 'prepare'] }); // Prepares Docker environment
|
|
||||||
}
|
|
||||||
|
|
||||||
prepareDocker().then(() => console.log('Docker environment prepared successfully.'));
|
|
||||||
```
|
|
||||||
|
|
||||||
**Building Docker Images:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { Npmci } from '@ship.zone/npmci';
|
|
||||||
|
|
||||||
async function buildDockerImages() {
|
|
||||||
const npmciInstance = new Npmci();
|
|
||||||
await npmciInstance.start();
|
|
||||||
|
|
||||||
await npmciInstance.dockerManager.handleCli({ _: ['docker', 'build'] }); // Builds Docker images
|
|
||||||
}
|
|
||||||
|
|
||||||
buildDockerImages().then(() => console.log('Docker images built successfully.'));
|
|
||||||
```
|
|
||||||
|
|
||||||
**Testing Docker Images:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { Npmci } from '@ship.zone/npmci';
|
|
||||||
|
|
||||||
async function testDockerImages() {
|
|
||||||
const npmciInstance = new Npmci();
|
|
||||||
await npmciInstance.start();
|
|
||||||
|
|
||||||
await npmciInstance.dockerManager.handleCli({ _: ['docker', 'test'] }); // Tests Docker images
|
|
||||||
}
|
|
||||||
|
|
||||||
testDockerImages().then(() => console.log('Docker images tested successfully.'));
|
|
||||||
```
|
|
||||||
|
|
||||||
**Publishing Docker Images:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { Npmci } from '@ship.zone/npmci';
|
|
||||||
|
|
||||||
async function pushDockerImages() {
|
|
||||||
const npmciInstance = new Npmci();
|
|
||||||
await npmciInstance.start();
|
|
||||||
|
|
||||||
await npmciInstance.dockerManager.handleCli({ _: ['docker', 'push'] }); // Pushes Docker images to registry
|
|
||||||
}
|
|
||||||
|
|
||||||
pushDockerImages().then(() => console.log('Docker images pushed successfully.'));
|
|
||||||
```
|
|
||||||
|
|
||||||
### 5. Managing Docker Registries
|
|
||||||
|
|
||||||
`npmci` can handle multiple Docker registries and allows for easy integration within your CI pipeline.
|
|
||||||
|
|
||||||
**Logging in to Docker Registries:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { Npmci } from '@ship.zone/npmci';
|
|
||||||
|
|
||||||
async function loginToDockerRegistries() {
|
|
||||||
const npmciInstance = new Npmci();
|
|
||||||
await npmciInstance.start();
|
|
||||||
|
|
||||||
await npmciInstance.dockerManager.handleCli({ _: ['docker', 'login'] }); // Logs into all configured Docker registries
|
|
||||||
}
|
|
||||||
|
|
||||||
loginToDockerRegistries().then(() => console.log('Logged into Docker registries.'));
|
|
||||||
```
|
|
||||||
|
|
||||||
**Pulling Docker Images:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { Npmci } from '@ship.zone/npmci';
|
|
||||||
|
|
||||||
async function pullDockerImages() {
|
|
||||||
const npmciInstance = new Npmci();
|
|
||||||
await npmciInstance.start();
|
|
||||||
|
|
||||||
await npmciInstance.dockerManager.handleCli({ _: ['docker', 'pull', 'registry.gitlab.com/mygroup/myrepo'] }); // Pulls Docker images from a registry
|
|
||||||
}
|
|
||||||
|
|
||||||
pullDockerImages().then(() => console.log('Docker images pulled successfully.'));
|
|
||||||
```
|
|
||||||
|
|
||||||
### 6. SSH Key Management
|
|
||||||
|
|
||||||
`npmci` also simplifies the management of SSH keys, which is crucial for accessing private repositories and servers.
|
|
||||||
|
|
||||||
**Preparing SSH Keys:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { Npmci } from '@ship.zone/npmci';
|
|
||||||
|
|
||||||
async function prepareSshKeys() {
|
|
||||||
const npmciInstance = new Npmci();
|
|
||||||
await npmciInstance.start();
|
|
||||||
|
|
||||||
await npmciInstance.sshManager.handleCli({ _: ['ssh', 'prepare'] }); // Prepares SSH keys from environment variables
|
|
||||||
}
|
|
||||||
|
|
||||||
prepareSshKeys().then(() => console.log('SSH keys prepared successfully.'));
|
|
||||||
```
|
|
||||||
|
|
||||||
### 7. Cloudron Integration
|
|
||||||
|
|
||||||
For users deploying applications on Cloudron, `npmci` provides a set of utilities for automating Cloudron tasks.
|
|
||||||
|
|
||||||
**Deploying to Cloudron:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { Npmci } from '@ship.zone/npmci';
|
|
||||||
|
|
||||||
async function deployToCloudron() {
|
|
||||||
const npmciInstance = new Npmci();
|
|
||||||
await npmciInstance.start();
|
|
||||||
|
|
||||||
await npmciInstance.cloudronManager.handleCli({
|
|
||||||
_: ['cloudron', 'deploy']
|
|
||||||
}); // Deploys application to Cloudron platform
|
|
||||||
}
|
|
||||||
|
|
||||||
deployToCloudron().then(() => console.log('Deployment to Cloudron completed.'));
|
|
||||||
```
|
|
||||||
|
|
||||||
**Preparing Cloudron Manifest:**
|
|
||||||
Before deployment, replace version placeholders in the Cloudron Manifest:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { Npmci } from '@ship.zone/npmci';
|
|
||||||
import * as fs from 'fs';
|
|
||||||
import * as path from 'path';
|
|
||||||
|
|
||||||
async function prepareCloudronManifest(version: string) {
|
|
||||||
const manifestPath = path.join(process.cwd(), "CloudronManifest.json");
|
|
||||||
let manifestFile = fs.readFileSync(manifestPath, { encoding: 'utf-8' });
|
|
||||||
manifestFile = manifestFile.replace(/##version##/g, version);
|
|
||||||
fs.writeFileSync(manifestPath, manifestFile);
|
|
||||||
console.log('CloudronManifest prepared');
|
|
||||||
}
|
|
||||||
|
|
||||||
async function deployWithPreparedManifest() {
|
|
||||||
const npmciInstance = new Npmci();
|
|
||||||
await npmciInstance.start();
|
|
||||||
|
|
||||||
await prepareCloudronManifest('1.0.0');
|
|
||||||
await npmciInstance.cloudronManager.handleCli({
|
|
||||||
_: ['cloudron', 'deploy']
|
|
||||||
}); // Deploys application to Cloudron platform
|
|
||||||
}
|
|
||||||
|
|
||||||
deployWithPreparedManifest().then(() => console.log('Deployment to Cloudron with manifest preparation completed.'));
|
|
||||||
```
|
|
||||||
|
|
||||||
### 8. Webhook Triggers
|
|
||||||
|
|
||||||
`npmci` supports webhook triggers, allowing you to trigger builds and other activities based on various conditions.
|
|
||||||
|
|
||||||
**Triggering Webhooks:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { Npmci } from '@ship.zone/npmci';
|
|
||||||
|
|
||||||
async function triggerWebhooks() {
|
|
||||||
const npmciInstance = new Npmci();
|
|
||||||
await npmciInstance.start();
|
|
||||||
|
|
||||||
await npmciInstance.triggerManager.handleCli({
|
|
||||||
_: ['trigger']
|
|
||||||
}); // Triggers webhooks based on environment variables
|
|
||||||
}
|
|
||||||
|
|
||||||
triggerWebhooks().then(() => console.log('Webhooks triggered successfully.'));
|
|
||||||
```
|
|
||||||
|
|
||||||
### 9. Using the bash Helper
|
|
||||||
|
|
||||||
`npmci` includes a bash helper for executing commands within a bash shell, useful for various custom tasks.
|
|
||||||
|
|
||||||
**Using bash to Execute Commands:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { bash } from '@ship.zone/npmci';
|
|
||||||
|
|
||||||
async function runCustomBashCommand(command: string) {
|
|
||||||
const output = await bash(command);
|
|
||||||
console.log('Command output:', output);
|
|
||||||
}
|
|
||||||
|
|
||||||
runCustomBashCommand('echo Hello World').then(() => console.log('Custom command executed successfully.'));
|
|
||||||
```
|
|
||||||
|
|
||||||
### Full Features and Use Cases
|
|
||||||
|
|
||||||
Below is a comprehensive set of features and use cases supported by `npmci`. This section ensures you can take full advantage of the library's capabilities in multiple scenarios.
|
|
||||||
|
|
||||||
### Comprehensive Docker Workflow
|
|
||||||
|
|
||||||
**Step-by-step Docker Image Handling:**
|
|
||||||
|
|
||||||
1. **Detect and Build All Dockerfiles:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { Npmci } from '@ship.zone/npmci';
|
|
||||||
|
|
||||||
async function detectAndBuildDockerfiles() {
|
|
||||||
const npmciInstance = new Npmci();
|
|
||||||
await npmciInstance.start();
|
|
||||||
const dockerfiles = await npmciInstance.dockerManager.getDockerfiles();
|
|
||||||
console.log('Dockerfiles detected:', dockerfiles.map(d => d.filePath));
|
|
||||||
|
|
||||||
await npmciInstance.dockerManager.handleCli({ _: ['docker', 'build'] });
|
|
||||||
console.log('Dockerfiles built successfully.');
|
|
||||||
}
|
|
||||||
|
|
||||||
detectAndBuildDockerfiles().then(() => console.log('Docker detection and build process completed.'));
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Test All Dockerfiles:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { Npmci } from '@ship.zone/npmci';
|
|
||||||
|
|
||||||
async function testAllDockerfiles() {
|
|
||||||
const npmciInstance = new Npmci();
|
|
||||||
await npmciInstance.start();
|
|
||||||
await npmciInstance.dockerManager.handleCli({ _: ['docker', 'test'] });
|
|
||||||
console.log('Dockerfiles tested successfully.');
|
|
||||||
}
|
|
||||||
|
|
||||||
testAllDockerfiles().then(() => console.log('Docker testing process completed.'));
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Push Dockerfiles to a Registry:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { Npmci } from '@ship.zone/npmci';
|
|
||||||
|
|
||||||
async function pushDockerfilesToRegistry() {
|
|
||||||
const npmciInstance = new Npmci();
|
|
||||||
await npmciInstance.start();
|
|
||||||
|
|
||||||
await npmciInstance.dockerManager.handleCli({ _: ['docker', 'push'] });
|
|
||||||
console.log('Dockerfiles pushed to registry successfully.');
|
|
||||||
}
|
|
||||||
|
|
||||||
pushDockerfilesToRegistry().then(() => console.log('Docker push process completed.'));
|
|
||||||
```
|
|
||||||
|
|
||||||
**Dockerfile Class Example:**
|
|
||||||
|
|
||||||
Here's a snippet showcasing how the `Dockerfile` class can be used to handle Dockerfile-specific operations:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { Dockerfile } from '@ship.zone/npmci';
|
|
||||||
|
|
||||||
async function handleDockerfileOperations() {
|
|
||||||
// Initialize Dockerfile instances
|
|
||||||
const dockerfile1 = new Dockerfile(/* required parameters */);
|
|
||||||
const dockerfile2 = new Dockerfile(/* required parameters */);
|
|
||||||
|
|
||||||
// Read and sort Dockerfiles
|
|
||||||
const dockerfiles = await Dockerfile.readDockerfiles(/* required parameters */);
|
|
||||||
const sortedDockerfiles = await Dockerfile.sortDockerfiles(dockerfiles);
|
|
||||||
|
|
||||||
// Build and Test Dockerfiles
|
|
||||||
await Dockerfile.buildDockerfiles(sortedDockerfiles);
|
|
||||||
await Dockerfile.testDockerfiles(sortedDockerfiles);
|
|
||||||
|
|
||||||
// Push Dockerfile images to a registry
|
|
||||||
for (const dockerfile of sortedDockerfiles) {
|
|
||||||
await dockerfile.push(/* registry and tag parameters */);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('Dockerfile operations completed successfully.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDockerfileOperations().then(() => console.log('Dockerfile processing flow completed.'));
|
|
||||||
```
|
```
|
||||||
|
|
||||||
This completes the comprehensive guide to `@ship.zone/npmci`. With the examples and explanations provided, you should be able to harness the full power and flexibility of the library to streamline your CI/CD processes effectively.
|
## 🐳 Docker Registry Authentication
|
||||||
undefined
|
|
||||||
|
SZCI supports automatic authentication with:
|
||||||
|
|
||||||
|
- GitLab CI Registry (via `CI_JOB_TOKEN`)
|
||||||
|
- Custom registries via environment variables
|
||||||
|
|
||||||
|
Set `NPMCI_LOGIN_DOCKER*` environment variables:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
NPMCI_LOGIN_DOCKER_1="registry.example.com|username|password"
|
||||||
|
NPMCI_LOGIN_DOCKER_2="another-registry.com|user2|pass2"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🏗️ Development
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- Deno 1.40+ installed
|
||||||
|
|
||||||
|
### Building from Source
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Clone the repository
|
||||||
|
git clone https://code.foss.global/ship.zone/szci.git
|
||||||
|
cd szci
|
||||||
|
|
||||||
|
# Compile for all platforms
|
||||||
|
deno task compile
|
||||||
|
|
||||||
|
# Compile for current platform only
|
||||||
|
deno compile --allow-all --output szci mod.ts
|
||||||
|
|
||||||
|
# Run tests
|
||||||
|
deno task test
|
||||||
|
|
||||||
|
# Development mode
|
||||||
|
deno task dev --help
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
|
||||||
|
Tests will be migrated to Deno's native test framework:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
deno task test
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📦 Binary Sizes
|
||||||
|
|
||||||
|
The standalone executables are approximately:
|
||||||
|
- Linux x64: ~800MB
|
||||||
|
- Linux ARM64: ~800MB
|
||||||
|
- macOS x64: ~796MB
|
||||||
|
- macOS ARM64: ~796MB
|
||||||
|
- Windows x64: ~804MB
|
||||||
|
|
||||||
|
Sizes include all dependencies and the Deno runtime.
|
||||||
|
|
||||||
|
## 🔄 Migration from npmci
|
||||||
|
|
||||||
|
If you're upgrading from the old `@ship.zone/npmci` package:
|
||||||
|
|
||||||
|
1. Update package references:
|
||||||
|
```sh
|
||||||
|
npm uninstall -g @ship.zone/npmci
|
||||||
|
npm install -g @ship.zone/szci
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Update CI configuration files - replace `npmci` with `szci`
|
||||||
|
|
||||||
|
3. The command interface remains the same, only the binary name changed
|
||||||
|
|
||||||
|
## 📝 License
|
||||||
|
|
||||||
|
MIT © Lossless GmbH
|
||||||
|
|
||||||
|
## 🔗 Links
|
||||||
|
|
||||||
|
- [Repository](https://code.foss.global/ship.zone/szci)
|
||||||
|
- [Issues](https://code.foss.global/ship.zone/szci/issues)
|
||||||
|
- [Changelog](./changelog.md)
|
||||||
|
|
||||||
|
## 🤝 Contributing
|
||||||
|
|
||||||
|
Contributions are welcome! Please feel free to submit a Pull Request.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Built with Deno 🦕**
|
||||||
|
|||||||
66
scripts/compile-all.sh
Executable file
66
scripts/compile-all.sh
Executable file
@@ -0,0 +1,66 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Get version from deno.json
|
||||||
|
VERSION=$(cat deno.json | grep -o '"version": *"[^"]*"' | cut -d'"' -f4)
|
||||||
|
BINARY_DIR="dist/binaries"
|
||||||
|
|
||||||
|
echo "================================================"
|
||||||
|
echo " SZCI Compilation Script"
|
||||||
|
echo " Version: ${VERSION}"
|
||||||
|
echo "================================================"
|
||||||
|
echo ""
|
||||||
|
echo "Compiling for all supported platforms..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Clean up old binaries and create fresh directory
|
||||||
|
rm -rf "$BINARY_DIR"
|
||||||
|
mkdir -p "$BINARY_DIR"
|
||||||
|
echo "→ Cleaned old binaries from $BINARY_DIR"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Linux x86_64
|
||||||
|
echo "→ Compiling for Linux x86_64..."
|
||||||
|
deno compile --allow-all --no-check --output "$BINARY_DIR/szci-linux-x64" \
|
||||||
|
--target x86_64-unknown-linux-gnu mod.ts
|
||||||
|
echo " ✓ Linux x86_64 complete"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Linux ARM64
|
||||||
|
echo "→ Compiling for Linux ARM64..."
|
||||||
|
deno compile --allow-all --no-check --output "$BINARY_DIR/szci-linux-arm64" \
|
||||||
|
--target aarch64-unknown-linux-gnu mod.ts
|
||||||
|
echo " ✓ Linux ARM64 complete"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# macOS x86_64
|
||||||
|
echo "→ Compiling for macOS x86_64..."
|
||||||
|
deno compile --allow-all --no-check --output "$BINARY_DIR/szci-macos-x64" \
|
||||||
|
--target x86_64-apple-darwin mod.ts
|
||||||
|
echo " ✓ macOS x86_64 complete"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# macOS ARM64
|
||||||
|
echo "→ Compiling for macOS ARM64..."
|
||||||
|
deno compile --allow-all --no-check --output "$BINARY_DIR/szci-macos-arm64" \
|
||||||
|
--target aarch64-apple-darwin mod.ts
|
||||||
|
echo " ✓ macOS ARM64 complete"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Windows x86_64
|
||||||
|
echo "→ Compiling for Windows x86_64..."
|
||||||
|
deno compile --allow-all --no-check --output "$BINARY_DIR/szci-windows-x64.exe" \
|
||||||
|
--target x86_64-pc-windows-msvc mod.ts
|
||||||
|
echo " ✓ Windows x86_64 complete"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
echo "================================================"
|
||||||
|
echo " Compilation Summary"
|
||||||
|
echo "================================================"
|
||||||
|
echo ""
|
||||||
|
ls -lh "$BINARY_DIR/" | tail -n +2
|
||||||
|
echo ""
|
||||||
|
echo "✓ All binaries compiled successfully!"
|
||||||
|
echo ""
|
||||||
|
echo "Binary location: $BINARY_DIR/"
|
||||||
|
echo ""
|
||||||
228
scripts/install-binary.js
Normal file
228
scripts/install-binary.js
Normal file
@@ -0,0 +1,228 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SZCI npm postinstall script
|
||||||
|
* Downloads the appropriate binary for the current platform from repository releases
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { platform, arch } from 'os';
|
||||||
|
import { existsSync, mkdirSync, writeFileSync, chmodSync, unlinkSync } from 'fs';
|
||||||
|
import { join, dirname } from 'path';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
import https from 'https';
|
||||||
|
import { pipeline } from 'stream';
|
||||||
|
import { promisify } from 'util';
|
||||||
|
import { createWriteStream } from 'fs';
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = dirname(__filename);
|
||||||
|
const streamPipeline = promisify(pipeline);
|
||||||
|
|
||||||
|
// Configuration
|
||||||
|
const REPO_BASE = 'https://code.foss.global/ship.zone/szci';
|
||||||
|
const VERSION = process.env.npm_package_version || '4.1.37';
|
||||||
|
|
||||||
|
function getBinaryInfo() {
|
||||||
|
const plat = platform();
|
||||||
|
const architecture = arch();
|
||||||
|
|
||||||
|
const platformMap = {
|
||||||
|
'darwin': 'macos',
|
||||||
|
'linux': 'linux',
|
||||||
|
'win32': 'windows'
|
||||||
|
};
|
||||||
|
|
||||||
|
const archMap = {
|
||||||
|
'x64': 'x64',
|
||||||
|
'arm64': 'arm64'
|
||||||
|
};
|
||||||
|
|
||||||
|
const mappedPlatform = platformMap[plat];
|
||||||
|
const mappedArch = archMap[architecture];
|
||||||
|
|
||||||
|
if (!mappedPlatform || !mappedArch) {
|
||||||
|
return { supported: false, platform: plat, arch: architecture };
|
||||||
|
}
|
||||||
|
|
||||||
|
let binaryName = `szci-${mappedPlatform}-${mappedArch}`;
|
||||||
|
if (plat === 'win32') {
|
||||||
|
binaryName += '.exe';
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
supported: true,
|
||||||
|
platform: mappedPlatform,
|
||||||
|
arch: mappedArch,
|
||||||
|
binaryName,
|
||||||
|
originalPlatform: plat
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function downloadFile(url, destination) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
console.log(`Downloading from: ${url}`);
|
||||||
|
|
||||||
|
// Follow redirects
|
||||||
|
const download = (url, redirectCount = 0) => {
|
||||||
|
if (redirectCount > 5) {
|
||||||
|
reject(new Error('Too many redirects'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
https.get(url, (response) => {
|
||||||
|
if (response.statusCode === 301 || response.statusCode === 302) {
|
||||||
|
console.log(`Following redirect to: ${response.headers.location}`);
|
||||||
|
download(response.headers.location, redirectCount + 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.statusCode !== 200) {
|
||||||
|
reject(new Error(`Failed to download: ${response.statusCode} ${response.statusMessage}`));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const totalSize = parseInt(response.headers['content-length'], 10);
|
||||||
|
let downloadedSize = 0;
|
||||||
|
let lastProgress = 0;
|
||||||
|
|
||||||
|
response.on('data', (chunk) => {
|
||||||
|
downloadedSize += chunk.length;
|
||||||
|
const progress = Math.round((downloadedSize / totalSize) * 100);
|
||||||
|
|
||||||
|
// Only log every 10% to reduce noise
|
||||||
|
if (progress >= lastProgress + 10) {
|
||||||
|
console.log(`Download progress: ${progress}%`);
|
||||||
|
lastProgress = progress;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const file = createWriteStream(destination);
|
||||||
|
|
||||||
|
pipeline(response, file, (err) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
} else {
|
||||||
|
console.log('Download complete!');
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).on('error', reject);
|
||||||
|
};
|
||||||
|
|
||||||
|
download(url);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
console.log('===========================================');
|
||||||
|
console.log(' SZCI - Binary Installation');
|
||||||
|
console.log('===========================================');
|
||||||
|
console.log('');
|
||||||
|
|
||||||
|
const binaryInfo = getBinaryInfo();
|
||||||
|
|
||||||
|
if (!binaryInfo.supported) {
|
||||||
|
console.error(`❌ Error: Unsupported platform/architecture: ${binaryInfo.platform}/${binaryInfo.arch}`);
|
||||||
|
console.error('');
|
||||||
|
console.error('Supported platforms:');
|
||||||
|
console.error(' • Linux (x64, arm64)');
|
||||||
|
console.error(' • macOS (x64, arm64)');
|
||||||
|
console.error(' • Windows (x64)');
|
||||||
|
console.error('');
|
||||||
|
console.error('If you believe your platform should be supported, please file an issue:');
|
||||||
|
console.error(' https://code.foss.global/ship.zone/szci/issues');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Platform: ${binaryInfo.platform} (${binaryInfo.originalPlatform})`);
|
||||||
|
console.log(`Architecture: ${binaryInfo.arch}`);
|
||||||
|
console.log(`Binary: ${binaryInfo.binaryName}`);
|
||||||
|
console.log(`Version: ${VERSION}`);
|
||||||
|
console.log('');
|
||||||
|
|
||||||
|
// Create dist/binaries directory if it doesn't exist
|
||||||
|
const binariesDir = join(__dirname, '..', 'dist', 'binaries');
|
||||||
|
if (!existsSync(binariesDir)) {
|
||||||
|
console.log('Creating binaries directory...');
|
||||||
|
mkdirSync(binariesDir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const binaryPath = join(binariesDir, binaryInfo.binaryName);
|
||||||
|
|
||||||
|
// Check if binary already exists and skip download
|
||||||
|
if (existsSync(binaryPath)) {
|
||||||
|
console.log('✓ Binary already exists, skipping download');
|
||||||
|
} else {
|
||||||
|
// Construct download URL
|
||||||
|
// Try release URL first, fall back to raw branch if needed
|
||||||
|
const releaseUrl = `${REPO_BASE}/releases/download/v${VERSION}/${binaryInfo.binaryName}`;
|
||||||
|
const fallbackUrl = `${REPO_BASE}/raw/branch/master/dist/binaries/${binaryInfo.binaryName}`;
|
||||||
|
|
||||||
|
console.log('Downloading platform-specific binary...');
|
||||||
|
console.log('This may take a moment depending on your connection speed.');
|
||||||
|
console.log('');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Try downloading from release
|
||||||
|
await downloadFile(releaseUrl, binaryPath);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(`Release download failed: ${err.message}`);
|
||||||
|
console.log('Trying fallback URL...');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Try fallback URL
|
||||||
|
await downloadFile(fallbackUrl, binaryPath);
|
||||||
|
} catch (fallbackErr) {
|
||||||
|
console.error(`❌ Error: Failed to download binary`);
|
||||||
|
console.error(` Primary URL: ${releaseUrl}`);
|
||||||
|
console.error(` Fallback URL: ${fallbackUrl}`);
|
||||||
|
console.error('');
|
||||||
|
console.error('This might be because:');
|
||||||
|
console.error('1. The release has not been created yet');
|
||||||
|
console.error('2. Network connectivity issues');
|
||||||
|
console.error('3. The version specified does not exist');
|
||||||
|
console.error('');
|
||||||
|
console.error('You can try:');
|
||||||
|
console.error('1. Installing from source: https://code.foss.global/ship.zone/szci');
|
||||||
|
console.error('2. Downloading the binary manually from the releases page');
|
||||||
|
console.error('3. Building from source with: deno task compile');
|
||||||
|
|
||||||
|
// Clean up partial download
|
||||||
|
if (existsSync(binaryPath)) {
|
||||||
|
unlinkSync(binaryPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`✓ Binary downloaded successfully`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// On Unix-like systems, ensure the binary is executable
|
||||||
|
if (binaryInfo.originalPlatform !== 'win32') {
|
||||||
|
try {
|
||||||
|
console.log('Setting executable permissions...');
|
||||||
|
chmodSync(binaryPath, 0o755);
|
||||||
|
console.log('✓ Binary permissions updated');
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`⚠️ Warning: Could not set executable permissions: ${err.message}`);
|
||||||
|
console.error(' You may need to manually run:');
|
||||||
|
console.error(` chmod +x ${binaryPath}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('');
|
||||||
|
console.log('✅ SZCI installation completed successfully!');
|
||||||
|
console.log('');
|
||||||
|
console.log('You can now use SZCI by running:');
|
||||||
|
console.log(' szci --help');
|
||||||
|
console.log('');
|
||||||
|
console.log('===========================================');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the installation
|
||||||
|
main().catch(err => {
|
||||||
|
console.error(`❌ Installation failed: ${err.message}`);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { tap, expect } from '@push.rocks/tapbundle';
|
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as smartpath from '@push.rocks/smartpath';
|
import * as smartpath from '@push.rocks/smartpath';
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* autocreated commitinfo by @push.rocks/commitinfo
|
* autocreated commitinfo by @push.rocks/commitinfo
|
||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@ship.zone/npmci',
|
name: '@ship.zone/szci',
|
||||||
version: '4.1.37',
|
version: '6.0.0',
|
||||||
description: 'A tool to streamline Node.js and Docker workflows within CI environments, particularly GitLab CI, providing various CI/CD utilities.'
|
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.'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
import * as plugins from '../npmci.plugins.js';
|
import * as plugins from '../szci.plugins.ts';
|
||||||
|
|
||||||
import { Npmci } from '../npmci.classes.npmci.js';
|
import { Szci } from '../szci.classes.szci.ts';
|
||||||
import { logger } from '../npmci.logging.js';
|
import { logger } from '../szci.logging.ts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* connects to cloudly
|
* connects to cloudly
|
||||||
*/
|
*/
|
||||||
export class CloudlyConnector {
|
export class CloudlyConnector {
|
||||||
public npmciRef: Npmci;
|
public szciRef: Szci;
|
||||||
|
|
||||||
constructor(npmciRefArg: Npmci) {
|
constructor(szciRefArg: Szci) {
|
||||||
this.npmciRef = npmciRefArg;
|
this.szciRef = szciRefArg;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async announceDockerContainer(
|
public async announceDockerContainer(
|
||||||
optionsArg: plugins.tsclass.container.IContainer,
|
optionsArg: plugins.tsclass.container.IContainer,
|
||||||
testCloudlyUrlArg?: string
|
testCloudlyUrlArg?: string
|
||||||
) {
|
) {
|
||||||
const cloudlyUrl = testCloudlyUrlArg || this.npmciRef.npmciConfig.getConfig().urlCloudly;
|
const cloudlyUrl = testCloudlyUrlArg || this.szciRef.npmciConfig.getConfig().urlCloudly;
|
||||||
if (!cloudlyUrl) {
|
if (!cloudlyUrl) {
|
||||||
logger.log(
|
logger.log(
|
||||||
'warn',
|
'warn',
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { Npmci } from './npmci.classes.npmci.js';
|
import { Szci } from './szci.classes.szci.ts';
|
||||||
import { Dockerfile } from './manager.docker/mod.classes.dockerfile.js';
|
import { Dockerfile } from './manager.docker/mod.classes.dockerfile.ts';
|
||||||
|
|
||||||
export const npmciInstance = new Npmci();
|
export const szciInstance = new Npmci();
|
||||||
|
|
||||||
export { Dockerfile, Npmci };
|
export { Dockerfile, Npmci };
|
||||||
|
|
||||||
export const runCli = async () => {
|
export const runCli = async () => {
|
||||||
await npmciInstance.start();
|
await szciInstance.start();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import { logger } from '../npmci.logging.js';
|
import { logger } from '../szci.logging.ts';
|
||||||
import * as plugins from './mod.plugins.js';
|
import * as plugins from './mod.plugins.ts';
|
||||||
import * as paths from '../npmci.paths.js';
|
import * as paths from '../szci.paths.ts';
|
||||||
import { bash } from '../npmci.bash.js';
|
import { bash } from '../szci.bash.ts';
|
||||||
import { Npmci } from '../npmci.classes.npmci.js';
|
import { Szci } from '../szci.classes.szci.ts';
|
||||||
|
|
||||||
export class NpmciCloudronManager {
|
export class SzciCloudronManager {
|
||||||
public npmciRef: Npmci;
|
public szciRef: Szci;
|
||||||
|
|
||||||
constructor(npmciArg: Npmci) {
|
constructor(szciArg: Szci) {
|
||||||
this.npmciRef = npmciArg;
|
this.szciRef = szciArg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,14 +44,14 @@ export class NpmciCloudronManager {
|
|||||||
logger.log('ok', 'cloudron cli installed');
|
logger.log('ok', 'cloudron cli installed');
|
||||||
|
|
||||||
// lets set the version in the CloudronManifest file
|
// lets set the version in the CloudronManifest file
|
||||||
await this.prepareCloudronManifest(this.npmciRef.npmciConfig.getConfig().projectInfo.npm.version);
|
await this.prepareCloudronManifest(this.szciRef.npmciConfig.getConfig().projectInfo.npm.version);
|
||||||
logger.log('ok', 'CloudronManifest prepared');
|
logger.log('ok', 'CloudronManifest prepared');
|
||||||
|
|
||||||
// lets figure out the docker image tag
|
// lets figure out the docker image tag
|
||||||
const dockerImageTag = await this.npmciRef.npmciConfig.kvStorage.readKey('latestPushedDockerTag');
|
const dockerImageTag = await this.szciRef.npmciConfig.kvStorage.readKey('latestPushedDockerTag');
|
||||||
const appName = this.npmciRef.npmciConfig.getConfig().cloudronAppName;
|
const appName = this.szciRef.npmciConfig.getConfig().cloudronAppName;
|
||||||
|
|
||||||
const cloudronEnvVar = process.env.NPMCI_LOGIN_CLOUDRON;
|
const cloudronEnvVar = Deno.env.get("NPMCI_LOGIN_CLOUDRON");
|
||||||
const cloudronServer = cloudronEnvVar.split('|')[0];
|
const cloudronServer = cloudronEnvVar.split('|')[0];
|
||||||
const cloudronToken = cloudronEnvVar.split('|')[1];
|
const cloudronToken = cloudronEnvVar.split('|')[1];
|
||||||
await bash(`cloudron update --server ${cloudronServer} --token ${cloudronToken} --image ${dockerImageTag} --app ${appName}`);
|
await bash(`cloudron update --server ${cloudronServer} --token ${cloudronToken} --image ${dockerImageTag} --app ${appName}`);
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export * from '../npmci.plugins.js';
|
export * from '../szci.plugins.ts';
|
||||||
@@ -1,20 +1,20 @@
|
|||||||
import { logger } from '../npmci.logging.js';
|
import { logger } from '../szci.logging.ts';
|
||||||
import * as plugins from './mod.plugins.js';
|
import * as plugins from './mod.plugins.ts';
|
||||||
import * as paths from '../npmci.paths.js';
|
import * as paths from '../szci.paths.ts';
|
||||||
import { bash } from '../npmci.bash.js';
|
import { bash } from '../szci.bash.ts';
|
||||||
|
|
||||||
// classes
|
// classes
|
||||||
import { Npmci } from '../npmci.classes.npmci.js';
|
import { Szci } from '../szci.classes.szci.ts';
|
||||||
import { Dockerfile } from './mod.classes.dockerfile.js';
|
import { Dockerfile } from './mod.classes.dockerfile.ts';
|
||||||
import { DockerRegistry } from './mod.classes.dockerregistry.js';
|
import { DockerRegistry } from './mod.classes.dockerregistry.ts';
|
||||||
import { RegistryStorage } from './mod.classes.registrystorage.js';
|
import { RegistryStorage } from './mod.classes.registrystorage.ts';
|
||||||
|
|
||||||
export class NpmciDockerManager {
|
export class SzciDockerManager {
|
||||||
public npmciRef: Npmci;
|
public szciRef: Szci;
|
||||||
public npmciRegistryStorage = new RegistryStorage();
|
public npmciRegistryStorage = new RegistryStorage();
|
||||||
|
|
||||||
constructor(npmciArg: Npmci) {
|
constructor(szciArg: Szci) {
|
||||||
this.npmciRef = npmciArg;
|
this.szciRef = szciArg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,24 +77,24 @@ export class NpmciDockerManager {
|
|||||||
*/
|
*/
|
||||||
public prepare = async () => {
|
public prepare = async () => {
|
||||||
// Always login to GitLab Registry
|
// Always login to GitLab Registry
|
||||||
if (process.env.GITLAB_CI) {
|
if (Deno.env.get("GITLAB_CI")) {
|
||||||
console.log('gitlab ci detected');
|
console.log('gitlab ci detected');
|
||||||
if (!process.env.CI_JOB_TOKEN || process.env.CI_JOB_TOKEN === '') {
|
if (!Deno.env.get("CI_JOB_TOKEN") || Deno.env.get("CI_JOB_TOKEN") === '') {
|
||||||
logger.log('error', 'Running in Gitlab CI, but no registry token specified by gitlab!');
|
logger.log('error', 'Running in Gitlab CI, but no registry token specified by gitlab!');
|
||||||
process.exit(1);
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
this.npmciRegistryStorage.addRegistry(
|
this.npmciRegistryStorage.addRegistry(
|
||||||
new DockerRegistry({
|
new DockerRegistry({
|
||||||
registryUrl: 'registry.gitlab.com',
|
registryUrl: 'registry.gitlab.com',
|
||||||
username: 'gitlab-ci-token',
|
username: 'gitlab-ci-token',
|
||||||
password: process.env.CI_JOB_TOKEN,
|
password: Deno.env.get("CI_JOB_TOKEN"),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle registries
|
// handle registries
|
||||||
await plugins.smartobject.forEachMinimatch(
|
await plugins.smartobject.forEachMinimatch(
|
||||||
process.env,
|
Deno.env.toObject(),
|
||||||
'NPMCI_LOGIN_DOCKER*',
|
'NPMCI_LOGIN_DOCKER*',
|
||||||
async (envString: string) => {
|
async (envString: string) => {
|
||||||
this.npmciRegistryStorage.addRegistry(DockerRegistry.fromEnvString(envString));
|
this.npmciRegistryStorage.addRegistry(DockerRegistry.fromEnvString(envString));
|
||||||
@@ -115,14 +115,14 @@ export class NpmciDockerManager {
|
|||||||
if (argvArg._.length >= 3 && argvArg._[2] !== 'npmextra') {
|
if (argvArg._.length >= 3 && argvArg._[2] !== 'npmextra') {
|
||||||
dockerRegistryUrls.push(argvArg._[2]);
|
dockerRegistryUrls.push(argvArg._[2]);
|
||||||
} else {
|
} else {
|
||||||
if (this.npmciRef.npmciConfig.getConfig().dockerRegistries.length === 0) {
|
if (this.szciRef.npmciConfig.getConfig().dockerRegistries.length === 0) {
|
||||||
logger.log(
|
logger.log(
|
||||||
'warn',
|
'warn',
|
||||||
`There are no docker registries listed in npmextra.json! This is strange!`
|
`There are no docker registries listed in npmextra.json! This is strange!`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
dockerRegistryUrls = dockerRegistryUrls.concat(
|
dockerRegistryUrls = dockerRegistryUrls.concat(
|
||||||
this.npmciRef.npmciConfig.getConfig().dockerRegistries
|
this.szciRef.npmciConfig.getConfig().dockerRegistries
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@ export class NpmciDockerManager {
|
|||||||
'error',
|
'error',
|
||||||
`Cannot push to registry ${dockerRegistryUrl}, because it was not found in the authenticated registry list.`
|
`Cannot push to registry ${dockerRegistryUrl}, because it was not found in the authenticated registry list.`
|
||||||
);
|
);
|
||||||
process.exit(1);
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
for (const dockerfile of dockerfileArray) {
|
for (const dockerfile of dockerfileArray) {
|
||||||
await dockerfile.push(dockerRegistryToPushTo, suffix);
|
await dockerfile.push(dockerRegistryToPushTo, suffix);
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import * as plugins from './mod.plugins.js';
|
import * as plugins from './mod.plugins.ts';
|
||||||
import * as paths from '../npmci.paths.js';
|
import * as paths from '../szci.paths.ts';
|
||||||
|
|
||||||
import { logger } from '../npmci.logging.js';
|
import { logger } from '../szci.logging.ts';
|
||||||
import { bash } from '../npmci.bash.js';
|
import { bash } from '../szci.bash.ts';
|
||||||
|
|
||||||
import { DockerRegistry } from './mod.classes.dockerregistry.js';
|
import { DockerRegistry } from './mod.classes.dockerregistry.ts';
|
||||||
import * as helpers from './mod.helpers.js';
|
import * as helpers from './mod.helpers.ts';
|
||||||
import { NpmciDockerManager } from './index.js';
|
import { SzciDockerManager } from './index.ts';
|
||||||
import { Npmci } from '../npmci.classes.npmci.js';
|
import { Szci } from '../szci.classes.szci.ts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* class Dockerfile represents a Dockerfile on disk in npmci
|
* class Dockerfile represents a Dockerfile on disk in npmci
|
||||||
@@ -20,7 +20,7 @@ export class Dockerfile {
|
|||||||
* @returns Promise<Dockerfile[]>
|
* @returns Promise<Dockerfile[]>
|
||||||
*/
|
*/
|
||||||
public static async readDockerfiles(
|
public static async readDockerfiles(
|
||||||
npmciDockerManagerRefArg: NpmciDockerManager
|
npmciDockerManagerRefArg: SzciDockerManager
|
||||||
): Promise<Dockerfile[]> {
|
): Promise<Dockerfile[]> {
|
||||||
const fileTree = await plugins.smartfile.fs.listFileTree(paths.cwd, 'Dockerfile*');
|
const fileTree = await plugins.smartfile.fs.listFileTree(paths.cwd, 'Dockerfile*');
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ export class Dockerfile {
|
|||||||
}
|
}
|
||||||
versionString = versionString.replace(
|
versionString = versionString.replace(
|
||||||
'##version##',
|
'##version##',
|
||||||
dockerfileInstanceArg.npmciDockerManagerRef.npmciRef.npmciConfig.getConfig().projectInfo.npm
|
dockerfileInstanceArg.npmciDockerManagerRef.szciRef.npmciConfig.getConfig().projectInfo.npm
|
||||||
.version
|
.version
|
||||||
);
|
);
|
||||||
return versionString;
|
return versionString;
|
||||||
@@ -194,7 +194,7 @@ export class Dockerfile {
|
|||||||
const argMatch = trimmedLine.match(/^ARG\s+([^\s=]+)(?:=(.*))?$/i);
|
const argMatch = trimmedLine.match(/^ARG\s+([^\s=]+)(?:=(.*))?$/i);
|
||||||
if (argMatch) {
|
if (argMatch) {
|
||||||
const argName = argMatch[1];
|
const argName = argMatch[1];
|
||||||
const argValue = argMatch[2] !== undefined ? argMatch[2] : process.env[argName] || '';
|
const argValue = argMatch[2] !== undefined ? argMatch[2] : Deno.env.get(argName) || '';
|
||||||
args[argName] = argValue;
|
args[argName] = argValue;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -236,7 +236,7 @@ export class Dockerfile {
|
|||||||
* returns the docker tag
|
* returns the docker tag
|
||||||
*/
|
*/
|
||||||
public static getDockerTagString(
|
public static getDockerTagString(
|
||||||
npmciDockerManagerRef: NpmciDockerManager,
|
npmciDockerManagerRef: SzciDockerManager,
|
||||||
registryArg: string,
|
registryArg: string,
|
||||||
repoArg: string,
|
repoArg: string,
|
||||||
versionArg: string,
|
versionArg: string,
|
||||||
@@ -244,7 +244,7 @@ export class Dockerfile {
|
|||||||
): string {
|
): string {
|
||||||
// determine wether the repo should be mapped accordingly to the registry
|
// determine wether the repo should be mapped accordingly to the registry
|
||||||
const mappedRepo =
|
const mappedRepo =
|
||||||
npmciDockerManagerRef.npmciRef.npmciConfig.getConfig().dockerRegistryRepoMap[registryArg];
|
npmciDockerManagerRef.szciRef.npmciConfig.getConfig().dockerRegistryRepoMap[registryArg];
|
||||||
const repo = (() => {
|
const repo = (() => {
|
||||||
if (mappedRepo) {
|
if (mappedRepo) {
|
||||||
return mappedRepo;
|
return mappedRepo;
|
||||||
@@ -264,27 +264,27 @@ export class Dockerfile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static async getDockerBuildArgs(
|
public static async getDockerBuildArgs(
|
||||||
npmciDockerManagerRef: NpmciDockerManager
|
npmciDockerManagerRef: SzciDockerManager
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
logger.log('info', 'checking for env vars to be supplied to the docker build');
|
logger.log('info', 'checking for env vars to be supplied to the docker build');
|
||||||
let buildArgsString: string = '';
|
let buildArgsString: string = '';
|
||||||
for (const dockerArgKey of Object.keys(
|
for (const dockerArgKey of Object.keys(
|
||||||
npmciDockerManagerRef.npmciRef.npmciConfig.getConfig().dockerBuildargEnvMap
|
npmciDockerManagerRef.szciRef.npmciConfig.getConfig().dockerBuildargEnvMap
|
||||||
)) {
|
)) {
|
||||||
const dockerArgOuterEnvVar =
|
const dockerArgOuterEnvVar =
|
||||||
npmciDockerManagerRef.npmciRef.npmciConfig.getConfig().dockerBuildargEnvMap[dockerArgKey];
|
npmciDockerManagerRef.szciRef.npmciConfig.getConfig().dockerBuildargEnvMap[dockerArgKey];
|
||||||
logger.log(
|
logger.log(
|
||||||
'note',
|
'note',
|
||||||
`docker ARG "${dockerArgKey}" maps to outer env var "${dockerArgOuterEnvVar}"`
|
`docker ARG "${dockerArgKey}" maps to outer env var "${dockerArgOuterEnvVar}"`
|
||||||
);
|
);
|
||||||
const targetValue = process.env[dockerArgOuterEnvVar];
|
const targetValue = Deno.env.get(dockerArgOuterEnvVar);
|
||||||
buildArgsString = `${buildArgsString} --build-arg ${dockerArgKey}="${targetValue}"`;
|
buildArgsString = `${buildArgsString} --build-arg ${dockerArgKey}="${targetValue}"`;
|
||||||
}
|
}
|
||||||
return buildArgsString;
|
return buildArgsString;
|
||||||
}
|
}
|
||||||
|
|
||||||
// INSTANCE
|
// INSTANCE
|
||||||
public npmciDockerManagerRef: NpmciDockerManager;
|
public npmciDockerManagerRef: SzciDockerManager;
|
||||||
|
|
||||||
public filePath: string;
|
public filePath: string;
|
||||||
public repo: string;
|
public repo: string;
|
||||||
@@ -299,15 +299,15 @@ export class Dockerfile {
|
|||||||
public localBaseDockerfile: Dockerfile;
|
public localBaseDockerfile: Dockerfile;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
dockerManagerRefArg: NpmciDockerManager,
|
dockerManagerRefArg: SzciDockerManager,
|
||||||
options: { filePath?: string; fileContents?: string | Buffer; read?: boolean }
|
options: { filePath?: string; fileContents?: string | Buffer; read?: boolean }
|
||||||
) {
|
) {
|
||||||
this.npmciDockerManagerRef = dockerManagerRefArg;
|
this.npmciDockerManagerRef = dockerManagerRefArg;
|
||||||
this.filePath = options.filePath;
|
this.filePath = options.filePath;
|
||||||
this.repo =
|
this.repo =
|
||||||
this.npmciDockerManagerRef.npmciRef.npmciEnv.repo.user +
|
this.npmciDockerManagerRef.szciRef.npmciEnv.repo.user +
|
||||||
'/' +
|
'/' +
|
||||||
this.npmciDockerManagerRef.npmciRef.npmciEnv.repo.repo;
|
this.npmciDockerManagerRef.szciRef.npmciEnv.repo.repo;
|
||||||
this.version = Dockerfile.dockerFileVersion(this, plugins.path.parse(options.filePath).base);
|
this.version = Dockerfile.dockerFileVersion(this, plugins.path.parse(options.filePath).base);
|
||||||
this.cleanTag = this.repo + ':' + this.version;
|
this.cleanTag = this.repo + ':' + this.version;
|
||||||
this.buildTag = this.cleanTag;
|
this.buildTag = this.cleanTag;
|
||||||
@@ -327,7 +327,7 @@ export class Dockerfile {
|
|||||||
logger.log('info', 'now building Dockerfile for ' + this.cleanTag);
|
logger.log('info', 'now building Dockerfile for ' + this.cleanTag);
|
||||||
const buildArgsString = await Dockerfile.getDockerBuildArgs(this.npmciDockerManagerRef);
|
const buildArgsString = await Dockerfile.getDockerBuildArgs(this.npmciDockerManagerRef);
|
||||||
const buildCommand = `docker build --label="version=${
|
const buildCommand = `docker build --label="version=${
|
||||||
this.npmciDockerManagerRef.npmciRef.npmciConfig.getConfig().projectInfo.npm.version
|
this.npmciDockerManagerRef.szciRef.npmciConfig.getConfig().projectInfo.npm.version
|
||||||
}" -t ${this.buildTag} -f ${this.filePath} ${buildArgsString} .`;
|
}" -t ${this.buildTag} -f ${this.filePath} ${buildArgsString} .`;
|
||||||
await bash(buildCommand);
|
await bash(buildCommand);
|
||||||
return;
|
return;
|
||||||
@@ -350,13 +350,13 @@ export class Dockerfile {
|
|||||||
await bash(`docker inspect --format="{{index .RepoDigests 0}}" ${this.pushTag}`)
|
await bash(`docker inspect --format="{{index .RepoDigests 0}}" ${this.pushTag}`)
|
||||||
).split('@')[1];
|
).split('@')[1];
|
||||||
console.log(`The image ${this.pushTag} has digest ${imageDigest}`);
|
console.log(`The image ${this.pushTag} has digest ${imageDigest}`);
|
||||||
await this.npmciDockerManagerRef.npmciRef.cloudlyConnector.announceDockerContainer({
|
await this.npmciDockerManagerRef.szciRef.cloudlyConnector.announceDockerContainer({
|
||||||
registryUrl: this.pushTag,
|
registryUrl: this.pushTag,
|
||||||
tag: this.buildTag,
|
tag: this.buildTag,
|
||||||
labels: [],
|
labels: [],
|
||||||
version: this.npmciDockerManagerRef.npmciRef.npmciConfig.getConfig().projectInfo.npm.version,
|
version: this.npmciDockerManagerRef.szciRef.npmciConfig.getConfig().projectInfo.npm.version,
|
||||||
});
|
});
|
||||||
await this.npmciDockerManagerRef.npmciRef.npmciConfig.kvStorage.writeKey(
|
await this.npmciDockerManagerRef.szciRef.npmciConfig.kvStorage.writeKey(
|
||||||
'latestPushedDockerTag',
|
'latestPushedDockerTag',
|
||||||
this.pushTag
|
this.pushTag
|
||||||
);
|
);
|
||||||
@@ -381,7 +381,7 @@ export class Dockerfile {
|
|||||||
* tests the Dockerfile;
|
* tests the Dockerfile;
|
||||||
*/
|
*/
|
||||||
public async test() {
|
public async test() {
|
||||||
const testFile: string = plugins.path.join(paths.NpmciTestDir, 'test_' + this.version + '.sh');
|
const testFile: string = plugins.path.join(paths.SzciTestDir, 'test_' + this.version + '.sh');
|
||||||
const testFileExists: boolean = plugins.smartfile.fs.fileExistsSync(testFile);
|
const testFileExists: boolean = plugins.smartfile.fs.fileExistsSync(testFile);
|
||||||
if (testFileExists) {
|
if (testFileExists) {
|
||||||
// run tests
|
// run tests
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { logger } from '../npmci.logging.js';
|
import { logger } from '../szci.logging.ts';
|
||||||
import * as plugins from './mod.plugins.js';
|
import * as plugins from './mod.plugins.ts';
|
||||||
import { bash } from '../npmci.bash.js';
|
import { bash } from '../szci.bash.ts';
|
||||||
|
|
||||||
export interface IDockerRegistryConstructorOptions {
|
export interface IDockerRegistryConstructorOptions {
|
||||||
registryUrl: string;
|
registryUrl: string;
|
||||||
@@ -23,7 +23,7 @@ export class DockerRegistry {
|
|||||||
const dockerRegexResultArray = envString.split('|');
|
const dockerRegexResultArray = envString.split('|');
|
||||||
if (dockerRegexResultArray.length !== 3) {
|
if (dockerRegexResultArray.length !== 3) {
|
||||||
logger.log('error', 'malformed docker env var...');
|
logger.log('error', 'malformed docker env var...');
|
||||||
process.exit(1);
|
Deno.exit(1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const registryUrl = dockerRegexResultArray[0].replace('https://', '').replace('http://', '');
|
const registryUrl = dockerRegexResultArray[0].replace('https://', '').replace('http://', '');
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { logger } from '../npmci.logging.js';
|
import { logger } from '../szci.logging.ts';
|
||||||
import * as plugins from './mod.plugins.js';
|
import * as plugins from './mod.plugins.ts';
|
||||||
|
|
||||||
import { DockerRegistry } from './mod.classes.dockerregistry.js';
|
import { DockerRegistry } from './mod.classes.dockerregistry.ts';
|
||||||
|
|
||||||
export class RegistryStorage {
|
export class RegistryStorage {
|
||||||
objectMap = new plugins.lik.ObjectMap<DockerRegistry>();
|
objectMap = new plugins.lik.ObjectMap<DockerRegistry>();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { logger } from '../npmci.logging.js';
|
import { logger } from '../szci.logging.ts';
|
||||||
import * as plugins from './mod.plugins.js';
|
import * as plugins from './mod.plugins.ts';
|
||||||
import * as paths from '../npmci.paths.js';
|
import * as paths from '../szci.paths.ts';
|
||||||
|
|
||||||
import { Dockerfile } from './mod.classes.dockerfile.js';
|
import { Dockerfile } from './mod.classes.dockerfile.ts';
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export * from '../npmci.plugins.js';
|
export * from '../szci.plugins.ts';
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import { logger } from '../npmci.logging.js';
|
import { logger } from '../szci.logging.ts';
|
||||||
import * as plugins from './mod.plugins.js';
|
import * as plugins from './mod.plugins.ts';
|
||||||
import { bash, bashNoError } from '../npmci.bash.js';
|
import { bash, bashNoError } from '../szci.bash.ts';
|
||||||
import { Npmci } from '../npmci.classes.npmci.js';
|
import { Szci } from '../szci.classes.szci.ts';
|
||||||
|
|
||||||
export class NpmciGitManager {
|
export class SzciGitManager {
|
||||||
public npmciRef: Npmci;
|
public szciRef: Szci;
|
||||||
|
|
||||||
constructor(npmciRefArg: Npmci) {
|
constructor(szciRefArg: Szci) {
|
||||||
this.npmciRef = npmciRefArg;
|
this.szciRef = szciRefArg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,12 +30,12 @@ export class NpmciGitManager {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public mirror = async () => {
|
public mirror = async () => {
|
||||||
const githubToken = process.env.NPMCI_GIT_GITHUBTOKEN;
|
const githubToken = Deno.env.get("NPMCI_GIT_GITHUBTOKEN");
|
||||||
const githubUser = process.env.NPMCI_GIT_GITHUBGROUP || this.npmciRef.npmciEnv.repo.user;
|
const githubUser = Deno.env.get("NPMCI_GIT_GITHUBGROUP") || this.szciRef.npmciEnv.repo.user;
|
||||||
const githubRepo = process.env.NPMCI_GIT_GITHUB || this.npmciRef.npmciEnv.repo.repo;
|
const githubRepo = Deno.env.get("NPMCI_GIT_GITHUB") || this.szciRef.npmciEnv.repo.repo;
|
||||||
if (
|
if (
|
||||||
this.npmciRef.npmciConfig.getConfig().projectInfo.npm.packageJson.private === true ||
|
this.szciRef.npmciConfig.getConfig().projectInfo.npm.packageJson.private === true ||
|
||||||
this.npmciRef.npmciConfig.getConfig().npmAccessLevel === 'private'
|
this.szciRef.npmciConfig.getConfig().npmAccessLevel === 'private'
|
||||||
) {
|
) {
|
||||||
logger.log(
|
logger.log(
|
||||||
'warn',
|
'warn',
|
||||||
@@ -65,7 +65,7 @@ export class NpmciGitManager {
|
|||||||
await bashNoError('git remote rm mirror');
|
await bashNoError('git remote rm mirror');
|
||||||
} else {
|
} else {
|
||||||
logger.log('error', `cannot find NPMCI_GIT_GITHUBTOKEN env var!`);
|
logger.log('error', `cannot find NPMCI_GIT_GITHUBTOKEN env var!`);
|
||||||
process.exit(1);
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export * from '../npmci.plugins.js';
|
export * from '../szci.plugins.ts';
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import * as plugins from '../npmci.plugins.js';
|
import * as plugins from '../szci.plugins.ts';
|
||||||
import * as paths from '../npmci.paths.js';
|
import * as paths from '../szci.paths.ts';
|
||||||
|
|
||||||
import { logger } from '../npmci.logging.js';
|
import { logger } from '../szci.logging.ts';
|
||||||
import { bash, bashNoError, nvmAvailable } from '../npmci.bash.js';
|
import { bash, bashNoError, nvmAvailable } from '../szci.bash.ts';
|
||||||
import { Npmci } from '../npmci.classes.npmci.js';
|
import { Szci } from '../szci.classes.szci.ts';
|
||||||
|
|
||||||
export class NpmciNodeJsManager {
|
export class SzciNodeJsManager {
|
||||||
public npmciRef: Npmci;
|
public szciRef: Szci;
|
||||||
|
|
||||||
constructor(npmciRefArg: Npmci) {
|
constructor(szciRefArg: Szci) {
|
||||||
this.npmciRef = npmciRefArg;
|
this.szciRef = szciRefArg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,14 +25,14 @@ export class NpmciNodeJsManager {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logger.log('error', `>>npmci node ...<< action >>${action}<< not supported`);
|
logger.log('error', `>>npmci node ...<< action >>${action}<< not supported`);
|
||||||
process.exit(1);
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.log(
|
logger.log(
|
||||||
'error',
|
'error',
|
||||||
`>>npmci node ...<< cli arguments invalid... Please read the documentation.`
|
`>>npmci node ...<< cli arguments invalid... Please read the documentation.`
|
||||||
);
|
);
|
||||||
process.exit(1);
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ export class NpmciNodeJsManager {
|
|||||||
await bash('npm -v');
|
await bash('npm -v');
|
||||||
|
|
||||||
// lets look for further config
|
// lets look for further config
|
||||||
const config = await this.npmciRef.npmciConfig.getConfig();
|
const config = await this.szciRef.npmciConfig.getConfig();
|
||||||
logger.log('info', 'Now checking for needed global npm tools...');
|
logger.log('info', 'Now checking for needed global npm tools...');
|
||||||
for (const npmTool of config.npmGlobalTools) {
|
for (const npmTool of config.npmGlobalTools) {
|
||||||
logger.log('info', `Checking for global "${npmTool}"`);
|
logger.log('info', `Checking for global "${npmTool}"`);
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import * as plugins from './mod.plugins.js';
|
import * as plugins from './mod.plugins.ts';
|
||||||
import * as paths from '../npmci.paths.js';
|
import * as paths from '../szci.paths.ts';
|
||||||
|
|
||||||
import { logger } from '../npmci.logging.js';
|
import { logger } from '../szci.logging.ts';
|
||||||
import { bash, bashNoError, nvmAvailable } from '../npmci.bash.js';
|
import { bash, bashNoError, nvmAvailable } from '../szci.bash.ts';
|
||||||
import { Npmci } from '../npmci.classes.npmci.js';
|
import { Szci } from '../szci.classes.szci.ts';
|
||||||
|
|
||||||
export class NpmciNpmManager {
|
export class SzciNpmManager {
|
||||||
public npmciRef: Npmci;
|
public szciRef: Szci;
|
||||||
|
|
||||||
constructor(npmciRefArg: Npmci) {
|
constructor(szciRefArg: Szci) {
|
||||||
this.npmciRef = npmciRefArg;
|
this.szciRef = szciRefArg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,14 +37,14 @@ export class NpmciNpmManager {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logger.log('error', `>>npmci npm ...<< action >>${action}<< not supported`);
|
logger.log('error', `>>npmci npm ...<< action >>${action}<< not supported`);
|
||||||
process.exit(1);
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.log(
|
logger.log(
|
||||||
'info',
|
'info',
|
||||||
`>>npmci npm ...<< cli arguments invalid... Please read the documentation.`
|
`>>npmci npm ...<< cli arguments invalid... Please read the documentation.`
|
||||||
);
|
);
|
||||||
process.exit(1);
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,10 +53,10 @@ export class NpmciNpmManager {
|
|||||||
*/
|
*/
|
||||||
public async prepare() {
|
public async prepare() {
|
||||||
logger.log('info', 'running >>npm prepare<<');
|
logger.log('info', 'running >>npm prepare<<');
|
||||||
const config = this.npmciRef.npmciConfig.getConfig();
|
const config = this.szciRef.npmciConfig.getConfig();
|
||||||
let npmrcFileString: string = '';
|
let npmrcFileString: string = '';
|
||||||
await plugins.smartobject.forEachMinimatch(
|
await plugins.smartobject.forEachMinimatch(
|
||||||
process.env,
|
Deno.env.toObject(),
|
||||||
'NPMCI_TOKEN_NPM*',
|
'NPMCI_TOKEN_NPM*',
|
||||||
(npmEnvArg: string) => {
|
(npmEnvArg: string) => {
|
||||||
if (!npmEnvArg) {
|
if (!npmEnvArg) {
|
||||||
@@ -83,14 +83,14 @@ export class NpmciNpmManager {
|
|||||||
logger.log('info', 'found one or more access tokens');
|
logger.log('info', 'found one or more access tokens');
|
||||||
} else {
|
} else {
|
||||||
logger.log('error', 'no access token found! Exiting!');
|
logger.log('error', 'no access token found! Exiting!');
|
||||||
process.exit(1);
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// lets save it to disk
|
// lets save it to disk
|
||||||
plugins.smartfile.memory.toFsSync(npmrcFileString, '/root/.npmrc');
|
plugins.smartfile.memory.toFsSync(npmrcFileString, '/root/.npmrc');
|
||||||
|
|
||||||
// lets set the cache directory
|
// lets set the cache directory
|
||||||
await bash(`npm config set cache ${paths.NpmciCacheDir} --global `);
|
await bash(`npm config set cache ${paths.SzciCacheDir} --global `);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -103,10 +103,10 @@ export class NpmciNpmManager {
|
|||||||
let npmAccessCliString = ``;
|
let npmAccessCliString = ``;
|
||||||
let npmRegistryCliString = ``;
|
let npmRegistryCliString = ``;
|
||||||
let publishVerdaccioAsWell = false;
|
let publishVerdaccioAsWell = false;
|
||||||
const config = this.npmciRef.npmciConfig.getConfig();
|
const config = this.szciRef.npmciConfig.getConfig();
|
||||||
const availableRegistries: string[] = [];
|
const availableRegistries: string[] = [];
|
||||||
await plugins.smartobject.forEachMinimatch(
|
await plugins.smartobject.forEachMinimatch(
|
||||||
process.env,
|
Deno.env.toObject(),
|
||||||
'NPMCI_TOKEN_NPM*',
|
'NPMCI_TOKEN_NPM*',
|
||||||
(npmEnvArg: string) => {
|
(npmEnvArg: string) => {
|
||||||
availableRegistries.push(npmEnvArg.split('|')[0]);
|
availableRegistries.push(npmEnvArg.split('|')[0]);
|
||||||
@@ -127,7 +127,7 @@ export class NpmciNpmManager {
|
|||||||
npmRegistryCliString = `--registry=https://${config.npmRegistryUrl}`;
|
npmRegistryCliString = `--registry=https://${config.npmRegistryUrl}`;
|
||||||
} else {
|
} else {
|
||||||
logger.log('error', `no registry url specified. Can't publish!`);
|
logger.log('error', `no registry url specified. Can't publish!`);
|
||||||
process.exit(1);
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let publishCommand = `npm publish ${npmAccessCliString} ${npmRegistryCliString} `;
|
let publishCommand = `npm publish ${npmAccessCliString} ${npmRegistryCliString} `;
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export * from '../npmci.plugins.js';
|
export * from '../szci.plugins.ts';
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import * as plugins from './mod.plugins.js';
|
import * as plugins from './mod.plugins.ts';
|
||||||
import * as paths from '../npmci.paths.js';
|
import * as paths from '../szci.paths.ts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cleans npmci config files
|
* cleans npmci config files
|
||||||
*/
|
*/
|
||||||
export let clean = async (): Promise<void> => {
|
export let clean = async (): Promise<void> => {
|
||||||
plugins.smartfile.fs.removeSync(paths.NpmciPackageConfig);
|
plugins.smartfile.fs.removeSync(paths.SzciPackageConfig);
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export * from '../npmci.plugins.js';
|
export * from '../szci.plugins.ts';
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import * as plugins from './mod.plugins.js';
|
import * as plugins from './mod.plugins.ts';
|
||||||
import { bash } from '../npmci.bash.js';
|
import { bash } from '../szci.bash.ts';
|
||||||
|
|
||||||
export let command = async () => {
|
export let command = async () => {
|
||||||
let wrappedCommand: string = '';
|
let wrappedCommand: string = '';
|
||||||
let argvArray = process.argv;
|
let argvArray = ['deno', 'mod.ts', ...Deno.args];
|
||||||
for (let i = 3; i < argvArray.length; i++) {
|
for (let i = 3; i < argvArray.length; i++) {
|
||||||
wrappedCommand = wrappedCommand + argvArray[i];
|
wrappedCommand = wrappedCommand + argvArray[i];
|
||||||
if (i + 1 !== argvArray.length) {
|
if (i + 1 !== argvArray.length) {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export * from '../npmci.plugins.js';
|
export * from '../szci.plugins.ts';
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import * as plugins from './plugins.js';
|
import * as plugins from './plugins.ts';
|
||||||
import * as paths from '../npmci.paths.js';
|
import * as paths from '../szci.paths.ts';
|
||||||
import { logger } from '../npmci.logging.js';
|
import { logger } from '../szci.logging.ts';
|
||||||
import { Npmci } from '../npmci.classes.npmci.js';
|
import { Szci } from '../szci.classes.szci.ts';
|
||||||
|
|
||||||
export const handleCli = async (npmciRefArg: Npmci, argvArg: any) => {
|
export const handleCli = async (szciRefArg: Szci, argvArg: any) => {
|
||||||
logger.log('info', 'checking execution context');
|
logger.log('info', 'checking execution context');
|
||||||
const presentRunnerTags = process.env.CI_RUNNER_TAGS.split(',').map((stringArg) =>
|
const presentRunnerTags = Deno.env.get("CI_RUNNER_TAGS").split(',').map((stringArg) =>
|
||||||
stringArg.trim()
|
stringArg.trim()
|
||||||
);
|
);
|
||||||
let allDesiredGitlabRunnerTagsPresent = true;
|
let allDesiredGitlabRunnerTagsPresent = true;
|
||||||
for (const desiredRunnerTag of npmciRefArg.npmciConfig.getConfig().gitlabRunnerTags) {
|
for (const desiredRunnerTag of szciRefArg.npmciConfig.getConfig().gitlabRunnerTags) {
|
||||||
if (!presentRunnerTags.includes(desiredRunnerTag)) {
|
if (!presentRunnerTags.includes(desiredRunnerTag)) {
|
||||||
allDesiredGitlabRunnerTagsPresent = false;
|
allDesiredGitlabRunnerTagsPresent = false;
|
||||||
logger.log(
|
logger.log(
|
||||||
@@ -19,6 +19,6 @@ export const handleCli = async (npmciRefArg: Npmci, argvArg: any) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!allDesiredGitlabRunnerTagsPresent) {
|
if (!allDesiredGitlabRunnerTagsPresent) {
|
||||||
process.exit(1);
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export * from '../npmci.plugins.js';
|
export * from '../szci.plugins.ts';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { logger } from '../npmci.logging.js';
|
import { logger } from '../szci.logging.ts';
|
||||||
import * as plugins from './mod.plugins.js';
|
import * as plugins from './mod.plugins.ts';
|
||||||
let sshInstance: plugins.smartssh.SshInstance;
|
let sshInstance: plugins.smartssh.SshInstance;
|
||||||
|
|
||||||
export let handleCli = async (argvArg: any) => {
|
export let handleCli = async (argvArg: any) => {
|
||||||
@@ -11,11 +11,11 @@ export let handleCli = async (argvArg: any) => {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
logger.log('error', `action >>${action}<< not supported`);
|
logger.log('error', `action >>${action}<< not supported`);
|
||||||
process.exit(1);
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.log('error', `>>npmci ssh ...<< please specify an action!`);
|
logger.log('error', `>>npmci ssh ...<< please specify an action!`);
|
||||||
process.exit(1);
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -31,8 +31,8 @@ const notUndefined = (stringArg: string) => {
|
|||||||
*/
|
*/
|
||||||
export let prepare = async () => {
|
export let prepare = async () => {
|
||||||
sshInstance = new plugins.smartssh.SshInstance(); // init ssh instance
|
sshInstance = new plugins.smartssh.SshInstance(); // init ssh instance
|
||||||
plugins.smartobject.forEachMinimatch(process.env, 'NPMCI_SSHKEY_*', evaluateSshEnv);
|
plugins.smartobject.forEachMinimatch(Deno.env.toObject(), 'NPMCI_SSHKEY_*', evaluateSshEnv);
|
||||||
if (!process.env.NPMTS_TEST) {
|
if (!Deno.env.get("NPMTS_TEST")) {
|
||||||
sshInstance.writeToDisk();
|
sshInstance.writeToDisk();
|
||||||
} else {
|
} else {
|
||||||
logger.log('info', 'In test mode, so not storing SSH keys to disk!');
|
logger.log('info', 'In test mode, so not storing SSH keys to disk!');
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export * from '../npmci.plugins.js';
|
export * from '../szci.plugins.ts';
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import * as plugins from './mod.plugins.js';
|
import * as plugins from './mod.plugins.ts';
|
||||||
import { bash } from '../npmci.bash.js';
|
import { bash } from '../szci.bash.ts';
|
||||||
import { logger } from '../npmci.logging.js';
|
import { logger } from '../szci.logging.ts';
|
||||||
|
|
||||||
const triggerValueRegex =
|
const triggerValueRegex =
|
||||||
/^([a-zA-Z0-9\.]*)\|([a-zA-Z0-9\.]*)\|([a-zA-Z0-9\.]*)\|([a-zA-Z0-9\.]*)\|?([a-zA-Z0-9\.\-\/]*)/;
|
/^([a-zA-Z0-9\.]*)\|([a-zA-Z0-9\.]*)\|([a-zA-Z0-9\.]*)\|([a-zA-Z0-9\.]*)\|?([a-zA-Z0-9\.\-\/]*)/;
|
||||||
|
|
||||||
export let trigger = async () => {
|
export let trigger = async () => {
|
||||||
logger.log('info', 'now running triggers');
|
logger.log('info', 'now running triggers');
|
||||||
await plugins.smartobject.forEachMinimatch(process.env, 'NPMCI_TRIGGER_*', evaluateTrigger);
|
await plugins.smartobject.forEachMinimatch(Deno.env.toObject(), 'NPMCI_TRIGGER_*', evaluateTrigger);
|
||||||
};
|
};
|
||||||
|
|
||||||
const evaluateTrigger = async (triggerEnvVarArg) => {
|
const evaluateTrigger = async (triggerEnvVarArg) => {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export * from '../npmci.plugins.js';
|
export * from '../szci.plugins.ts';
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
import * as plugins from './npmci.plugins.js';
|
|
||||||
|
|
||||||
|
|
||||||
// env
|
|
||||||
import { NpmciEnv } from './npmci.classes.npmcienv.js';
|
|
||||||
import { NpmciInfo } from './npmci.classes.npmciinfo.js';
|
|
||||||
import { NpmciCli } from './npmci.classes.npmcicli.js';
|
|
||||||
import { NpmciConfig } from './npmci.classes.npmciconfig.js';
|
|
||||||
|
|
||||||
// connectors
|
|
||||||
import { CloudlyConnector } from './connector.cloudly/cloudlyconnector.js';
|
|
||||||
|
|
||||||
// managers
|
|
||||||
import { NpmciCloudronManager } from './manager.cloudron/index.js';
|
|
||||||
import { NpmciDockerManager } from './manager.docker/index.js';
|
|
||||||
import { NpmciGitManager } from './manager.git/index.js';
|
|
||||||
import { NpmciNodeJsManager } from './manager.nodejs/index.js';
|
|
||||||
import { NpmciNpmManager } from './manager.npm/index.js';
|
|
||||||
|
|
||||||
export class Npmci {
|
|
||||||
public analytics: plugins.smartanalytics.Analytics;
|
|
||||||
public cloudlyConnector: CloudlyConnector;
|
|
||||||
|
|
||||||
public npmciEnv: NpmciEnv;
|
|
||||||
public npmciInfo: NpmciInfo;
|
|
||||||
public npmciConfig: NpmciConfig;
|
|
||||||
public npmciCli: NpmciCli;
|
|
||||||
|
|
||||||
// managers
|
|
||||||
public cloudronManager: NpmciCloudronManager;
|
|
||||||
public dockerManager: NpmciDockerManager;
|
|
||||||
public gitManager: NpmciGitManager;
|
|
||||||
public nodejsManager: NpmciNodeJsManager;
|
|
||||||
public npmManager: NpmciNpmManager;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.analytics = new plugins.smartanalytics.Analytics({
|
|
||||||
apiEndPoint: 'https://pubapi.lossless.one/analytics',
|
|
||||||
projectId: 'gitzone',
|
|
||||||
appName: 'npmci',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public async start() {
|
|
||||||
this.cloudlyConnector = new CloudlyConnector(this);
|
|
||||||
this.npmciEnv = new NpmciEnv(this);
|
|
||||||
this.npmciInfo = new NpmciInfo(this);
|
|
||||||
await this.npmciInfo.printToConsole();
|
|
||||||
this.npmciCli = new NpmciCli(this);
|
|
||||||
this.npmciConfig = new NpmciConfig(this);
|
|
||||||
await this.npmciConfig.init();
|
|
||||||
|
|
||||||
// managers
|
|
||||||
this.cloudronManager = new NpmciCloudronManager(this);
|
|
||||||
this.dockerManager = new NpmciDockerManager(this);
|
|
||||||
this.gitManager = new NpmciGitManager(this);
|
|
||||||
this.nodejsManager = new NpmciNodeJsManager(this);
|
|
||||||
this.npmManager = new NpmciNpmManager(this);
|
|
||||||
this.npmciCli.startParse();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
import * as plugins from './npmci.plugins.js';
|
|
||||||
import { Npmci } from './npmci.classes.npmci.js';
|
|
||||||
|
|
||||||
export class NpmciEnv {
|
|
||||||
public npmciRef: Npmci;
|
|
||||||
|
|
||||||
public repoString: string;
|
|
||||||
public repo: plugins.smartstring.GitRepo;
|
|
||||||
|
|
||||||
constructor(npmciRefArg: Npmci) {
|
|
||||||
this.npmciRef = npmciRefArg;
|
|
||||||
if (!this.repoString && process.env.GITLAB_CI) {
|
|
||||||
this.repoString = process.env.CI_REPOSITORY_URL;
|
|
||||||
}
|
|
||||||
if (!this.repoString && process.env.NPMCI_COMPUTED_REPOURL) {
|
|
||||||
this.repoString = process.env.NPMCI_COMPUTED_REPOURL;
|
|
||||||
}
|
|
||||||
if (!this.repoString) {
|
|
||||||
this.repoString = 'https://undefined:undefined@github.com/undefined/undefined.git';
|
|
||||||
}
|
|
||||||
this.repo = new plugins.smartstring.GitRepo(this.repoString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
import * as plugins from './npmci.plugins.js';
|
|
||||||
import * as paths from './npmci.paths.js';
|
|
||||||
import { logger } from './npmci.logging.js';
|
|
||||||
import { Npmci } from './npmci.classes.npmci.js';
|
|
||||||
|
|
||||||
export class NpmciInfo {
|
|
||||||
public npmciRef: Npmci;
|
|
||||||
public projectInfo = new plugins.projectinfo.ProjectinfoNpm(paths.NpmciPackageRoot);
|
|
||||||
|
|
||||||
constructor(npmciArg: Npmci) {
|
|
||||||
this.npmciRef = npmciArg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async printToConsole() {
|
|
||||||
await logger.log('info', `npmci version: ${this.projectInfo.version}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import * as plugins from './npmci.plugins.js';
|
|
||||||
|
|
||||||
export const cwd = process.cwd();
|
|
||||||
|
|
||||||
// package paths
|
|
||||||
export const NpmciPackageRoot = plugins.path.join(
|
|
||||||
plugins.smartpath.get.dirnameFromImportMetaUrl(import.meta.url),
|
|
||||||
'../'
|
|
||||||
);
|
|
||||||
export const NpmciPackageConfig = plugins.path.join(NpmciPackageRoot, './config.json');
|
|
||||||
|
|
||||||
// project paths
|
|
||||||
export const NpmciProjectDir = cwd;
|
|
||||||
export const NpmciProjectNogitDir = plugins.path.join(NpmciProjectDir, './.nogit');
|
|
||||||
export const NpmciTestDir = plugins.path.join(cwd, './test');
|
|
||||||
export const NpmciCacheDir = plugins.path.join(cwd, './.npmci_cache');
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { logger } from './npmci.logging.js';
|
import { logger } from './szci.logging.ts';
|
||||||
import * as plugins from './npmci.plugins.js';
|
import * as plugins from './szci.plugins.ts';
|
||||||
import * as paths from './npmci.paths.js';
|
import * as paths from './szci.paths.ts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wether nvm is available or not
|
* wether nvm is available or not
|
||||||
@@ -19,7 +19,7 @@ const npmciSmartshell = new plugins.smartshell.Smartshell({
|
|||||||
*/
|
*/
|
||||||
const checkToolsAvailable = async () => {
|
const checkToolsAvailable = async () => {
|
||||||
// check for nvm
|
// check for nvm
|
||||||
if (!process.env.NPMTS_TEST) {
|
if (!Deno.env.get('NPMTS_TEST')) {
|
||||||
if (
|
if (
|
||||||
(await npmciSmartshell.execSilent(`bash -c "source /usr/local/nvm/nvm.sh"`)).exitCode === 0
|
(await npmciSmartshell.execSilent(`bash -c "source /usr/local/nvm/nvm.sh"`)).exitCode === 0
|
||||||
) {
|
) {
|
||||||
@@ -55,10 +55,10 @@ export let bash = async (commandArg: string, retryArg: number = 2): Promise<stri
|
|||||||
retryArg = 0;
|
retryArg = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!process.env.NPMTS_TEST) {
|
if (!Deno.env.get('NPMTS_TEST')) {
|
||||||
// NPMTS_TEST is used during testing
|
// NPMTS_TEST is used during testing
|
||||||
for (let i = 0; i <= retryArg; i++) {
|
for (let i = 0; i <= retryArg; i++) {
|
||||||
if (process.env.DEBUG_NPMCI === 'true') {
|
if (Deno.env.get('DEBUG_NPMCI') === 'true') {
|
||||||
console.log(commandArg);
|
console.log(commandArg);
|
||||||
}
|
}
|
||||||
execResult = await npmciSmartshell.exec(commandArg);
|
execResult = await npmciSmartshell.exec(commandArg);
|
||||||
@@ -68,7 +68,7 @@ export let bash = async (commandArg: string, retryArg: number = 2): Promise<stri
|
|||||||
// something went wrong and retries are exhausted
|
// something went wrong and retries are exhausted
|
||||||
if (failOnError) {
|
if (failOnError) {
|
||||||
logger.log('error', 'something went wrong and retries are exhausted');
|
logger.log('error', 'something went wrong and retries are exhausted');
|
||||||
process.exit(1);
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
} else if (execResult.exitCode === 0) {
|
} else if (execResult.exitCode === 0) {
|
||||||
// everything went fine, or no error wanted
|
// everything went fine, or no error wanted
|
||||||
61
ts/szci.classes.szci.ts
Normal file
61
ts/szci.classes.szci.ts
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import * as plugins from './szci.plugins.ts';
|
||||||
|
|
||||||
|
|
||||||
|
// env
|
||||||
|
import { SzciEnv } from './szci.classes.szcienv.ts';
|
||||||
|
import { SzciInfo } from './szci.classes.szciinfo.ts';
|
||||||
|
import { SzciCli } from './szci.classes.szcicli.ts';
|
||||||
|
import { SzciConfig } from './szci.classes.szciconfig.ts';
|
||||||
|
|
||||||
|
// connectors
|
||||||
|
import { CloudlyConnector } from './connector.cloudly/cloudlyconnector.ts';
|
||||||
|
|
||||||
|
// managers
|
||||||
|
import { SzciCloudronManager } from './manager.cloudron/index.ts';
|
||||||
|
import { SzciDockerManager } from './manager.docker/index.ts';
|
||||||
|
import { SzciGitManager } from './manager.git/index.ts';
|
||||||
|
import { SzciNodeJsManager } from './manager.nodejs/index.ts';
|
||||||
|
import { SzciNpmManager } from './manager.npm/index.ts';
|
||||||
|
|
||||||
|
export class Szci {
|
||||||
|
public analytics: plugins.smartanalytics.Analytics;
|
||||||
|
public cloudlyConnector: CloudlyConnector;
|
||||||
|
|
||||||
|
public npmciEnv: SzciEnv;
|
||||||
|
public npmciInfo: SzciInfo;
|
||||||
|
public npmciConfig: SzciConfig;
|
||||||
|
public npmciCli: SzciCli;
|
||||||
|
|
||||||
|
// managers
|
||||||
|
public cloudronManager: SzciCloudronManager;
|
||||||
|
public dockerManager: SzciDockerManager;
|
||||||
|
public gitManager: SzciGitManager;
|
||||||
|
public nodejsManager: SzciNodeJsManager;
|
||||||
|
public npmManager: SzciNpmManager;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.analytics = new plugins.smartanalytics.Analytics({
|
||||||
|
apiEndPoint: 'https://pubapi.lossless.one/analytics',
|
||||||
|
projectId: 'gitzone',
|
||||||
|
appName: 'szci',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async start() {
|
||||||
|
this.cloudlyConnector = new CloudlyConnector(this);
|
||||||
|
this.npmciEnv = new SzciEnv(this);
|
||||||
|
this.npmciInfo = new SzciInfo(this);
|
||||||
|
await this.npmciInfo.printToConsole();
|
||||||
|
this.npmciCli = new SzciCli(this);
|
||||||
|
this.npmciConfig = new SzciConfig(this);
|
||||||
|
await this.npmciConfig.init();
|
||||||
|
|
||||||
|
// managers
|
||||||
|
this.cloudronManager = new SzciCloudronManager(this);
|
||||||
|
this.dockerManager = new SzciDockerManager(this);
|
||||||
|
this.gitManager = new SzciGitManager(this);
|
||||||
|
this.nodejsManager = new SzciNodeJsManager(this);
|
||||||
|
this.npmManager = new SzciNpmManager(this);
|
||||||
|
this.npmciCli.startParse();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
import { logger } from './npmci.logging.js';
|
import { logger } from './szci.logging.ts';
|
||||||
import * as plugins from './npmci.plugins.js';
|
import * as plugins from './szci.plugins.ts';
|
||||||
import * as paths from './npmci.paths.js';
|
import * as paths from './szci.paths.ts';
|
||||||
import { Npmci } from './npmci.classes.npmci.js';
|
import { Szci } from './szci.classes.szci.ts';
|
||||||
|
|
||||||
export class NpmciCli {
|
export class SzciCli {
|
||||||
public npmciRef: Npmci;
|
public szciRef: Szci;
|
||||||
public smartcli: plugins.smartcli.Smartcli;
|
public smartcli: plugins.smartcli.Smartcli;
|
||||||
|
|
||||||
constructor(npmciArg: Npmci) {
|
constructor(szciArg: Szci) {
|
||||||
this.npmciRef = npmciArg;
|
this.szciRef = szciArg;
|
||||||
this.smartcli = new plugins.smartcli.Smartcli();
|
this.smartcli = new plugins.smartcli.Smartcli();
|
||||||
this.smartcli.addVersion(this.npmciRef.npmciInfo.projectInfo.version);
|
this.smartcli.addVersion(this.szciRef.npmciInfo.version);
|
||||||
|
|
||||||
// clean
|
// clean
|
||||||
this.smartcli.addCommand('clean').subscribe(
|
this.smartcli.addCommand('clean').subscribe(
|
||||||
@@ -20,18 +20,18 @@ export class NpmciCli {
|
|||||||
},
|
},
|
||||||
(err) => {
|
(err) => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
process.exit(1);
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// cloudron
|
// cloudron
|
||||||
this.smartcli.addCommand('cloudron').subscribe(
|
this.smartcli.addCommand('cloudron').subscribe(
|
||||||
async (argv) => {
|
async (argv) => {
|
||||||
await this.npmciRef.cloudronManager.handleCli(argv);
|
await this.szciRef.cloudronManager.handleCli(argv);
|
||||||
},
|
},
|
||||||
(err) => {
|
(err) => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
process.exit(1);
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -43,47 +43,47 @@ export class NpmciCli {
|
|||||||
},
|
},
|
||||||
(err) => {
|
(err) => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
process.exit(1);
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// git
|
// git
|
||||||
this.smartcli.addCommand('git').subscribe(
|
this.smartcli.addCommand('git').subscribe(
|
||||||
async (argvArg) => {
|
async (argvArg) => {
|
||||||
await this.npmciRef.gitManager.handleCli(argvArg);
|
await this.szciRef.gitManager.handleCli(argvArg);
|
||||||
},
|
},
|
||||||
(err) => {
|
(err) => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
process.exit(1);
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// build
|
// build
|
||||||
this.smartcli.addCommand('docker').subscribe(
|
this.smartcli.addCommand('docker').subscribe(
|
||||||
async (argvArg) => {
|
async (argvArg) => {
|
||||||
await this.npmciRef.dockerManager.handleCli(argvArg);
|
await this.szciRef.dockerManager.handleCli(argvArg);
|
||||||
},
|
},
|
||||||
(err) => {
|
(err) => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
process.exit(1);
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// node
|
// node
|
||||||
this.smartcli.addCommand('node').subscribe(
|
this.smartcli.addCommand('node').subscribe(
|
||||||
async (argvArg) => {
|
async (argvArg) => {
|
||||||
await this.npmciRef.nodejsManager.handleCli(argvArg);
|
await this.szciRef.nodejsManager.handleCli(argvArg);
|
||||||
},
|
},
|
||||||
(err) => {
|
(err) => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
process.exit(1);
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// npm
|
// npm
|
||||||
this.smartcli.addCommand('npm').subscribe(
|
this.smartcli.addCommand('npm').subscribe(
|
||||||
async (argvArg) => {
|
async (argvArg) => {
|
||||||
await this.npmciRef.npmManager.handleCli(argvArg);
|
await this.szciRef.npmManager.handleCli(argvArg);
|
||||||
},
|
},
|
||||||
(err) => {
|
(err) => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
@@ -92,7 +92,7 @@ export class NpmciCli {
|
|||||||
|
|
||||||
this.smartcli.addCommand('precheck').subscribe(async (argvArg) => {
|
this.smartcli.addCommand('precheck').subscribe(async (argvArg) => {
|
||||||
const modPrecheck = await import('./mod_precheck/index.js');
|
const modPrecheck = await import('./mod_precheck/index.js');
|
||||||
await modPrecheck.handleCli(this.npmciRef, argvArg);
|
await modPrecheck.handleCli(this.szciRef, argvArg);
|
||||||
});
|
});
|
||||||
|
|
||||||
// trigger
|
// trigger
|
||||||
@@ -109,7 +109,7 @@ export class NpmciCli {
|
|||||||
},
|
},
|
||||||
(err) => {
|
(err) => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
process.exit(1);
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
import * as plugins from './npmci.plugins.js';
|
import * as plugins from './szci.plugins.ts';
|
||||||
import * as paths from './npmci.paths.js';
|
import * as paths from './szci.paths.ts';
|
||||||
|
|
||||||
import { logger } from './npmci.logging.js';
|
import { logger } from './szci.logging.ts';
|
||||||
import { Npmci } from './npmci.classes.npmci.js';
|
import { Szci } from './szci.classes.szci.ts';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the main config interface for npmci
|
* the main config interface for npmci
|
||||||
*/
|
*/
|
||||||
export interface INpmciOptions {
|
export interface ISzciOptions {
|
||||||
projectInfo: plugins.projectinfo.ProjectInfo;
|
projectInfo: plugins.projectinfo.ProjectInfo;
|
||||||
|
|
||||||
// npm
|
// npm
|
||||||
@@ -33,28 +33,28 @@ export interface INpmciOptions {
|
|||||||
/**
|
/**
|
||||||
* a config class for Npmci
|
* a config class for Npmci
|
||||||
*/
|
*/
|
||||||
export class NpmciConfig {
|
export class SzciConfig {
|
||||||
public npmciRef: Npmci;
|
public szciRef: Szci;
|
||||||
|
|
||||||
public npmciNpmextra: plugins.npmextra.Npmextra;
|
public npmciNpmextra: plugins.npmextra.Npmextra;
|
||||||
public kvStorage: plugins.npmextra.KeyValueStore;
|
public kvStorage: plugins.npmextra.KeyValueStore;
|
||||||
public npmciQenv: plugins.qenv.Qenv;
|
public npmciQenv: plugins.qenv.Qenv;
|
||||||
|
|
||||||
private configObject: INpmciOptions;
|
private configObject: ISzciOptions;
|
||||||
|
|
||||||
constructor(npmciRefArg: Npmci) {
|
constructor(szciRefArg: Szci) {
|
||||||
this.npmciRef = npmciRefArg;
|
this.szciRef = szciRefArg;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async init() {
|
public async init() {
|
||||||
this.npmciNpmextra = new plugins.npmextra.Npmextra(paths.cwd);
|
this.npmciNpmextra = new plugins.npmextra.Npmextra(paths.cwd);
|
||||||
this.kvStorage = new plugins.npmextra.KeyValueStore({
|
this.kvStorage = new plugins.npmextra.KeyValueStore({
|
||||||
typeArg: 'userHomeDir',
|
typeArg: 'userHomeDir',
|
||||||
identityArg: `.npmci_${this.npmciRef.npmciEnv.repo.user}_${this.npmciRef.npmciEnv.repo.repo}`,
|
identityArg: `.npmci_${this.szciRef.npmciEnv.repo.user}_${this.szciRef.npmciEnv.repo.repo}`,
|
||||||
});
|
});
|
||||||
this.npmciQenv = new plugins.qenv.Qenv(
|
this.npmciQenv = new plugins.qenv.Qenv(
|
||||||
paths.NpmciProjectDir,
|
paths.SzciProjectDir,
|
||||||
paths.NpmciProjectNogitDir,
|
paths.SzciProjectNogitDir,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -69,10 +69,10 @@ export class NpmciConfig {
|
|||||||
dockerBuildargEnvMap: {},
|
dockerBuildargEnvMap: {},
|
||||||
urlCloudly: await this.npmciQenv.getEnvVarOnDemand('NPMCI_URL_CLOUDLY'),
|
urlCloudly: await this.npmciQenv.getEnvVarOnDemand('NPMCI_URL_CLOUDLY'),
|
||||||
};
|
};
|
||||||
this.configObject = this.npmciNpmextra.dataFor<INpmciOptions>('npmci', this.configObject);
|
this.configObject = this.npmciNpmextra.dataFor<ISzciOptions>('szci', this.configObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getConfig(): INpmciOptions {
|
public getConfig(): ISzciOptions {
|
||||||
return this.configObject;
|
return this.configObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
23
ts/szci.classes.szcienv.ts
Normal file
23
ts/szci.classes.szcienv.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import * as plugins from './szci.plugins.ts';
|
||||||
|
import { Szci } from './szci.classes.szci.ts';
|
||||||
|
|
||||||
|
export class SzciEnv {
|
||||||
|
public szciRef: Szci;
|
||||||
|
|
||||||
|
public repoString: string;
|
||||||
|
public repo: plugins.smartstring.GitRepo;
|
||||||
|
|
||||||
|
constructor(szciRefArg: Szci) {
|
||||||
|
this.szciRef = szciRefArg;
|
||||||
|
if (!this.repoString && Deno.env.get("GITLAB_CI")) {
|
||||||
|
this.repoString = Deno.env.get("CI_REPOSITORY_URL");
|
||||||
|
}
|
||||||
|
if (!this.repoString && Deno.env.get("NPMCI_COMPUTED_REPOURL")) {
|
||||||
|
this.repoString = Deno.env.get("NPMCI_COMPUTED_REPOURL");
|
||||||
|
}
|
||||||
|
if (!this.repoString) {
|
||||||
|
this.repoString = 'https://undefined:undefined@github.com/undefined/undefined.git';
|
||||||
|
}
|
||||||
|
this.repo = new plugins.smartstring.GitRepo(this.repoString);
|
||||||
|
}
|
||||||
|
}
|
||||||
18
ts/szci.classes.szciinfo.ts
Normal file
18
ts/szci.classes.szciinfo.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import * as plugins from './szci.plugins.ts';
|
||||||
|
import * as paths from './szci.paths.ts';
|
||||||
|
import { logger } from './szci.logging.ts';
|
||||||
|
import { Szci } from './szci.classes.szci.ts';
|
||||||
|
import denoConfig from '../deno.json' with { type: 'json' };
|
||||||
|
|
||||||
|
export class SzciInfo {
|
||||||
|
public szciRef: Szci;
|
||||||
|
public version = denoConfig.version;
|
||||||
|
|
||||||
|
constructor(szciArg: Szci) {
|
||||||
|
this.szciRef = szciArg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async printToConsole() {
|
||||||
|
await logger.log('info', `szci version: ${this.version}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import * as plugins from './npmci.plugins.js';
|
import * as plugins from './szci.plugins.ts';
|
||||||
|
|
||||||
export const logger = new plugins.smartlog.Smartlog({
|
export const logger = new plugins.smartlog.Smartlog({
|
||||||
logContext: {
|
logContext: {
|
||||||
16
ts/szci.paths.ts
Normal file
16
ts/szci.paths.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import * as plugins from './szci.plugins.ts';
|
||||||
|
|
||||||
|
export const cwd = Deno.cwd();
|
||||||
|
|
||||||
|
// package paths
|
||||||
|
export const SzciPackageRoot = plugins.path.join(
|
||||||
|
plugins.smartpath.get.dirnameFromImportMetaUrl(import.meta.url),
|
||||||
|
'../'
|
||||||
|
);
|
||||||
|
export const SzciPackageConfig = plugins.path.join(SzciPackageRoot, './config.json');
|
||||||
|
|
||||||
|
// project paths
|
||||||
|
export const SzciProjectDir = cwd;
|
||||||
|
export const SzciProjectNogitDir = plugins.path.join(SzciProjectDir, './.nogit');
|
||||||
|
export const SzciTestDir = plugins.path.join(cwd, './test');
|
||||||
|
export const SzciCacheDir = plugins.path.join(cwd, './.npmci_cache');
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
// node native
|
// Deno std libraries
|
||||||
import * as path from 'path';
|
import * as path from '@std/path';
|
||||||
|
|
||||||
export { path };
|
export { path };
|
||||||
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"experimentalDecorators": true,
|
|
||||||
"useDefineForClassFields": false,
|
|
||||||
"target": "ES2022",
|
|
||||||
"module": "NodeNext",
|
|
||||||
"moduleResolution": "NodeNext",
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"verbatimModuleSyntax": true
|
|
||||||
},
|
|
||||||
"exclude": [
|
|
||||||
"dist_*/**/*.d.ts"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
64
uninstall.sh
Executable file
64
uninstall.sh
Executable file
@@ -0,0 +1,64 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# SZCI Uninstaller Script
|
||||||
|
# Removes SZCI from the system (installed via install.sh)
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# sudo bash uninstall.sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Check if running as root
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo "Please run as root (sudo bash uninstall.sh)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "================================================"
|
||||||
|
echo " SZCI Uninstaller"
|
||||||
|
echo " Serve Zone CI/CD Tool Removal"
|
||||||
|
echo "================================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Default installation directory
|
||||||
|
INSTALL_DIR="/opt/szci"
|
||||||
|
|
||||||
|
# Step 1: Remove global symlinks
|
||||||
|
echo "Checking for global symlinks..."
|
||||||
|
if [ -L "/usr/local/bin/szci" ]; then
|
||||||
|
echo "Removing symlink: /usr/local/bin/szci"
|
||||||
|
rm -f /usr/local/bin/szci
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -L "/usr/bin/szci" ]; then
|
||||||
|
echo "Removing symlink: /usr/bin/szci"
|
||||||
|
rm -f /usr/bin/szci
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Step 2: Remove installation directory
|
||||||
|
if [ -d "$INSTALL_DIR" ]; then
|
||||||
|
echo "Removing installation directory: $INSTALL_DIR"
|
||||||
|
rm -rf "$INSTALL_DIR"
|
||||||
|
else
|
||||||
|
echo "Installation directory not found: $INSTALL_DIR"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "================================================"
|
||||||
|
echo " SZCI Uninstallation Complete!"
|
||||||
|
echo "================================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check for npm global installation
|
||||||
|
NODE_PATH=$(which node 2>/dev/null || true)
|
||||||
|
if [ -n "$NODE_PATH" ]; then
|
||||||
|
NPM_PATH=$(dirname "$NODE_PATH")/npm
|
||||||
|
if [ -x "$NPM_PATH" ]; then
|
||||||
|
echo "If you installed SZCI via npm, you may want to uninstall it with:"
|
||||||
|
echo " npm uninstall -g @ship.zone/szci"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "SZCI has been removed from your system."
|
||||||
|
echo ""
|
||||||
Reference in New Issue
Block a user