Skip to content

Latest commit

 

History

History
981 lines (707 loc) · 45.3 KB

File metadata and controls

981 lines (707 loc) · 45.3 KB

🛠️ Local Development

Use this guide to build and run CloudVoyager locally. All developers should build the binary and run that — do not run directly from source. This ensures consistent behavior across environments and eliminates "works on my machine" issues.


✅ Prerequisites

  1. Node.js v20 LTS (required for npm run package — see warning below)
  2. npm (comes with Node.js)
  3. Bun (optional, only needed for experimental npm run package:bun)

WARNING — Node.js v22+ breaks SEA builds: npm run package uses Node.js Single Executable Applications (SEA) and the postject injection tool (v1.0.0-alpha.6). Node.js v22+ embeds the SEA sentinel string twice in its binary, which causes postject to fail with "Multiple occurrences of sentinel found in the binary". You must use Node.js v20 LTS to build binaries:

nvm install 20
nvm use 20
npm run package

This restriction only applies to building the binary (npm run package). Running tests, linting, and npm run build work fine on Node.js >=18.0.0.

Node.js version summary:

  • >=18.0.0 — minimum for running from source, tests, linting, bundling
  • v20 LTSrequired for npm run package (SEA binary builds)
  • v22+DO NOT USE for packaging (causes postject sentinel failure)

Install dependencies:

npm install

Key Dependencies

Production (25 total): protobufjs 7.2.0, commander 12.0.0, axios 1.6.0, ajv 8.12.0, winston 3.11.0, pdfmake 0.3.4, form-data 4.0.0, adm-zip 0.5.16, and others.

Dev: esbuild 0.27.3 (bundler), postject 1.0.0-alpha.6 (SEA injection), ava 6.4.1 (test runner), c8 10.1.3 (coverage), sinon 21.0.1 (mocking), esmock 2.7.3 (ESM module mocking), eslint 8.56.0.

Project metadata: version 1.1.2, ES modules ("type": "module"), bin entry cloudvoyagersrc/index.js.


📦 Building the Binary

CloudVoyager can be compiled into a standalone binary using two packaging backends. Both produce a self-contained binary that does not require Node.js or Bun to be installed on the target machine.

Node.js SEA (Default)

npm run package           # Build for current platform
node scripts/build.js --package --target=macos-x64  # Cross-compile for a different platform

Uses esbuild for bundling + Node.js Single Executable Applications (SEA) with V8 code cache. Builds for the current platform. This is the recommended method — it is stable and well-tested.

WARNING: Requires Node.js v20 LTS. Node.js v22+ causes a postject injection failure ("Multiple occurrences of sentinel"). Run nvm use 20 before packaging. See Prerequisites for details.

Build Pipeline Steps

The Node.js SEA build runs three stages internally:

  1. esbuild bundle — bundles all source into dist/cli.cjs (CJS format, minified, tree-shaken, .proto files loaded as text)
  2. SEA blob generation — Node.js generates dist/sea-prep.blob from the bundle
  3. postject injection — injects the SEA blob into a copy of the Node.js binary → dist/bin/cloudvoyager-{platform}-{arch}
  4. macOS only — code signature removal and re-signing is required after injection

Bun Compile (Experimental)

npm run package:bun           # Build for current platform
npm run package:bun:cross     # Cross-compile 5 platform binaries

Uses Bun's single-step compile — source goes directly to a native binary with no intermediate bundle. Bun is installed as an optional dependency — no global install required. While faster to build, Bun binaries may silently crash at runtime in some environments, so this is considered experimental.

Output

Platform Output Binary Build Method
macOS (Apple Silicon) dist/bin/cloudvoyager-macos-arm64 Node.js SEA
macOS (Intel) dist/bin/cloudvoyager-macos-x64 Node.js SEA
Linux (x64) dist/bin/cloudvoyager-linux-x64 Node.js SEA
Linux (ARM64) dist/bin/cloudvoyager-linux-arm64 Node.js SEA
Windows (x64) dist/bin/cloudvoyager-win-x64.exe Node.js SEA
Windows (ARM64) dist/bin/cloudvoyager-win-arm64.exe Node.js SEA

Note: npm run package builds for your current platform only using Node.js SEA. Use --target=<platform> to cross-compile for a different platform (e.g., --target=macos-x64 builds an x64 binary on an ARM64 Mac). In CI, 6 parallel jobs build binaries for each platform.

If you only need the bundled JavaScript file (without the standalone binary), you can run:

npm run build

This creates dist/cli.cjs, which can be run with node dist/cli.cjs <command> [options].


🖥️ Desktop App

CloudVoyager Desktop is an Electron-based GUI that wraps the CLI binary. It provides a wizard interface for configuring and running migrations without using the terminal. Past successful runs are saved in a sidebar history for quick access to reports.

Prerequisites

  • Node.js v20+ and npm
  • The CLI binary built and available in dist/bin/ (run npm run package first)

Running in Development

cd desktop
npm install

# Copy the CLI binary into desktop/resources/cli/
node scripts/prepare-cli.js

# Launch the app
npm start

In development mode, if no CLI binary is found in resources/cli/, the app falls back to running node src/index.js directly.

Building for Distribution

Each command builds a platform-specific installer:

cd desktop
npm run build:linux-x64     # Linux x64 .AppImage
npm run build:linux-arm64    # Linux ARM64 .AppImage
npm run build:mac-arm64      # macOS ARM64 .dmg
npm run build:mac-x64        # macOS x64 .dmg
npm run build:win-x64        # Windows x64 .exe (NSIS)
npm run build:win-arm64      # Windows ARM64 .exe (NSIS)

Note: You must place the correct CLI binary in desktop/resources/cli/ before building. The prepare-cli.js script copies the binary for your current platform from dist/bin/.

Output

Platform Output
Linux (x64) dist/desktop/CloudVoyager Desktop-*.AppImage
Linux (ARM64) dist/desktop/CloudVoyager Desktop-*.AppImage
macOS (Apple Silicon) dist/desktop/CloudVoyager Desktop-*.dmg
macOS (Intel) dist/desktop/CloudVoyager Desktop-*.dmg
Windows (x64) dist/desktop/CloudVoyager Desktop Setup *.exe
Windows (ARM64) dist/desktop/CloudVoyager Desktop Setup *.exe

See the Desktop App Guide for the full user guide.


🏃 Running the Binary

After building, make it executable (macOS/Linux) and run it directly:

# Make executable (macOS/Linux only)
chmod +x dist/bin/cloudvoyager-macos-arm64

# Run it
./dist/bin/cloudvoyager-macos-arm64 migrate -c migrate-config.json --verbose

Quick Start Examples

# Validate a config file
./cloudvoyager validate -c config.json

# Test connections to SonarQube Server and SonarQube Cloud
./cloudvoyager test -c config.json

# Transfer a single project
./cloudvoyager transfer -c config.json --verbose

# Dry-run a full migration (no changes made)
./cloudvoyager migrate -c migrate-config.json --verbose --dry-run

# Run a full migration
./cloudvoyager migrate -c migrate-config.json --verbose

# Run a full migration with auto-tuning
./cloudvoyager migrate -c migrate-config.json --verbose --auto-tune

# Sync metadata only (issues + hotspots)
./cloudvoyager sync-metadata -c migrate-config.json --verbose

# Verify migration completeness
./cloudvoyager verify -c migrate-config.json --verbose

# Verify only specific components
./cloudvoyager verify -c migrate-config.json --verbose --only issue-metadata,hotspot-metadata

# Check transfer status
./cloudvoyager status -c config.json

# Reset state (clear sync history)
./cloudvoyager reset -c config.json

Tip: Use --verbose on any command to enable debug-level logging. Substitute ./cloudvoyager with your actual binary path (e.g. ./dist/bin/cloudvoyager-macos-arm64).

See the CLI Reference section below for all available flags and exhaustive usage examples.


📖 CLI Reference

This section documents every command and flag available in CloudVoyager. The examples use ./cloudvoyager as shorthand — substitute with your actual binary path (e.g. ./dist/bin/cloudvoyager-macos-arm64).

Global Flag

Flag Short Description
--version -V Print the CloudVoyager version number and exit
--help -h Display help for the command

validate — Validate configuration file

Flag Short Required Argument Description
--config <path> -c Yes File path Path to the configuration file to validate

Examples

# Validate a config file
./cloudvoyager validate -c config.json

# Validate using short flag
./cloudvoyager validate -c config.json

test — Test connections to SonarQube Server and SonarQube Cloud

Flag Short Required Argument Description
--config <path> -c Yes File path Path to the configuration file containing connection details
--verbose -v No Enable debug-level logging for detailed output

Examples

# Test connections
./cloudvoyager test -c config.json

# Test connections with verbose output
./cloudvoyager test -c config.json --verbose

status — Show current synchronization status

Flag Short Required Argument Description
--config <path> -c Yes File path Path to the configuration file (reads the state file path from it)

Examples

# Check sync status
./cloudvoyager status -c config.json

reset — Reset state and clear sync history

Flag Short Required Argument Description
--config <path> -c Yes File path Path to the configuration file (reads the state file path from it)
--yes -y No Skip the confirmation prompt and reset immediately

Examples

# Reset state (will show a confirmation warning and exit)
./cloudvoyager reset -c config.json

# Reset state without confirmation
./cloudvoyager reset -c config.json --yes

# Reset state using short flags
./cloudvoyager reset -c config.json -y

transfer — Transfer a single project from SonarQube Server to SonarQube Cloud

Flag Short Required Argument Description
--config <path> -c Yes File path Path to the configuration file
--verbose -v No Enable debug-level logging for detailed output
--wait No Wait for the SonarQube Cloud analysis to complete before returning (blocks until the Compute Engine task finishes)
--concurrency <n> No Integer Override the maximum concurrency for I/O operations (source file extraction, hotspot extraction, etc.)
--max-memory <mb> No Integer Set the max heap size in MB; auto-restarts the process with increased heap if the current heap is too small
--auto-tune No Auto-detect hardware (CPU cores, available memory) and set optimal concurrency and memory values
--skip-all-branch-sync No Only sync the main branch (skip non-main branches). Equivalent to setting transfer.syncAllBranches: false in config
--force-restart No Discard checkpoint journal and start a fresh transfer from scratch
--force-fresh-extract No Discard extraction caches and re-extract all data from SonarQube Server
--force-unlock No Force release a stale lock file from a previous run
--show-progress No Display checkpoint progress status table and exit

Examples

# Basic transfer
./cloudvoyager transfer -c config.json

# Transfer with verbose logging
./cloudvoyager transfer -c config.json --verbose

# Transfer with verbose logging (short flag)
./cloudvoyager transfer -c config.json -v

# Transfer and wait for SonarQube Cloud analysis to finish
./cloudvoyager transfer -c config.json --wait

# Transfer with verbose logging and wait for analysis
./cloudvoyager transfer -c config.json --verbose --wait

# Transfer with custom concurrency (e.g. 8 parallel I/O operations)
./cloudvoyager transfer -c config.json --concurrency 8

# Transfer with verbose logging and custom concurrency
./cloudvoyager transfer -c config.json --verbose --concurrency 8

# Transfer with custom max memory (e.g. 4096 MB)
./cloudvoyager transfer -c config.json --max-memory 4096

# Transfer with verbose logging and custom max memory
./cloudvoyager transfer -c config.json --verbose --max-memory 4096

# Transfer with auto-tuned performance settings
./cloudvoyager transfer -c config.json --auto-tune

# Transfer with verbose logging and auto-tune
./cloudvoyager transfer -c config.json --verbose --auto-tune

# Transfer with all flags combined: verbose, wait, auto-tune
./cloudvoyager transfer -c config.json --verbose --wait --auto-tune

# Transfer with all manual performance flags: verbose, wait, concurrency, max-memory
./cloudvoyager transfer -c config.json --verbose --wait --concurrency 8 --max-memory 4096

# Transfer with concurrency, max-memory, and wait (no verbose)
./cloudvoyager transfer -c config.json --wait --concurrency 8 --max-memory 4096

# Transfer with auto-tune and wait
./cloudvoyager transfer -c config.json --wait --auto-tune

# Transfer with auto-tune and max-memory override
./cloudvoyager transfer -c config.json --auto-tune --max-memory 8192

# Transfer with verbose, auto-tune, and max-memory override
./cloudvoyager transfer -c config.json --verbose --auto-tune --max-memory 8192

# Show checkpoint progress without running a transfer
./cloudvoyager transfer -c config.json --show-progress

# Resume a previously interrupted transfer (automatic — just re-run)
./cloudvoyager transfer -c config.json --verbose

# Force restart from scratch (discard checkpoint journal)
./cloudvoyager transfer -c config.json --verbose --force-restart

# Re-extract all data but keep checkpoint journal
./cloudvoyager transfer -c config.json --verbose --force-fresh-extract

# Force release a stale lock from a crashed run
./cloudvoyager transfer -c config.json --verbose --force-unlock


migrate — Full migration from SonarQube Server to one or more SonarQube Cloud organizations

Flag Short Required Argument Description
--config <path> -c Yes File path Path to the migration configuration file
--verbose -v No Enable debug-level logging for detailed output
--wait No Wait for each SonarQube Cloud analysis to complete before proceeding
--dry-run No Extract data and generate project/key mappings without actually migrating any data
--skip-issue-metadata-sync No Skip syncing issue metadata (statuses, assignments, comments, tags) after transfer
--skip-hotspot-metadata-sync No Skip syncing hotspot metadata (statuses, comments) after transfer
--skip-quality-profile-sync No Skip syncing quality profiles (projects use default SonarQube Cloud profiles)
--concurrency <n> No Integer Override the maximum concurrency for I/O operations (applies to source extraction, hotspot extraction, issue sync, and hotspot sync)
--max-memory <mb> No Integer Set the max heap size in MB; auto-restarts with increased heap if needed
--project-concurrency <n> No Integer Maximum number of projects to migrate concurrently
--auto-tune No Auto-detect hardware and set optimal concurrency, memory, and project-concurrency values
--skip-all-branch-sync No Only sync the main branch of each project (skip non-main branches). Equivalent to setting transfer.syncAllBranches: false in config
--only <components> No Comma-separated list Only migrate specific components. Valid values: scan-data, scan-data-all-branches, portfolios, quality-gates, quality-profiles, permission-templates, permissions, issue-metadata, hotspot-metadata, project-settings
--force-restart No Discard migration journal and start a fresh migration from scratch
--force-unlock No Force release a stale lock file from a previous run

Examples

# Basic migration
./cloudvoyager migrate -c migrate-config.json

# Migration with verbose logging
./cloudvoyager migrate -c migrate-config.json --verbose

# Dry-run: extract data and show mappings without migrating
./cloudvoyager migrate -c migrate-config.json --dry-run

# Dry-run with verbose logging
./cloudvoyager migrate -c migrate-config.json --verbose --dry-run

# Migration and wait for each analysis to complete
./cloudvoyager migrate -c migrate-config.json --wait

# Migration with verbose logging and wait
./cloudvoyager migrate -c migrate-config.json --verbose --wait

# Migration skipping issue metadata sync (transfer code + hotspot metadata only)
./cloudvoyager migrate -c migrate-config.json --skip-issue-metadata-sync

# Migration skipping issue metadata sync with verbose logging
./cloudvoyager migrate -c migrate-config.json --verbose --skip-issue-metadata-sync

# Migration skipping hotspot metadata sync (transfer code + issue metadata only)
./cloudvoyager migrate -c migrate-config.json --skip-hotspot-metadata-sync

# Migration skipping hotspot metadata sync with verbose logging
./cloudvoyager migrate -c migrate-config.json --verbose --skip-hotspot-metadata-sync

# Migration skipping both issue and hotspot metadata sync (transfer code only)
./cloudvoyager migrate -c migrate-config.json --skip-issue-metadata-sync --skip-hotspot-metadata-sync

# Migration skipping both metadata syncs with verbose logging
./cloudvoyager migrate -c migrate-config.json --verbose --skip-issue-metadata-sync --skip-hotspot-metadata-sync

# Migration with custom I/O concurrency
./cloudvoyager migrate -c migrate-config.json --concurrency 8

# Migration with verbose logging and custom I/O concurrency
./cloudvoyager migrate -c migrate-config.json --verbose --concurrency 8

# Migration with custom max memory
./cloudvoyager migrate -c migrate-config.json --max-memory 4096

# Migration with verbose logging and custom max memory
./cloudvoyager migrate -c migrate-config.json --verbose --max-memory 4096

# Migration with project-level concurrency
./cloudvoyager migrate -c migrate-config.json --project-concurrency 3

# Migration with verbose logging and project concurrency
./cloudvoyager migrate -c migrate-config.json --verbose --project-concurrency 3

# Migration with auto-tuned settings
./cloudvoyager migrate -c migrate-config.json --auto-tune

# Migration with verbose logging and auto-tune
./cloudvoyager migrate -c migrate-config.json --verbose --auto-tune

# Migration with all manual performance flags
./cloudvoyager migrate -c migrate-config.json --verbose --wait --concurrency 8 --max-memory 4096 --project-concurrency 3

# Migration with auto-tune, wait, and verbose
./cloudvoyager migrate -c migrate-config.json --verbose --wait --auto-tune

# Migration with auto-tune and project concurrency override
./cloudvoyager migrate -c migrate-config.json --auto-tune --project-concurrency 5

# Migration with auto-tune, verbose, and max-memory override
./cloudvoyager migrate -c migrate-config.json --verbose --auto-tune --max-memory 8192

# Dry-run with auto-tune (preview settings and mappings)
./cloudvoyager migrate -c migrate-config.json --verbose --dry-run --auto-tune

# Migration with concurrency and skip issue metadata sync
./cloudvoyager migrate -c migrate-config.json --verbose --concurrency 8 --skip-issue-metadata-sync

# Migration with concurrency and skip hotspot metadata sync
./cloudvoyager migrate -c migrate-config.json --verbose --concurrency 8 --skip-hotspot-metadata-sync

# Migration with all performance flags and skip both metadata syncs
./cloudvoyager migrate -c migrate-config.json --verbose --wait --concurrency 8 --max-memory 4096 --project-concurrency 3 --skip-issue-metadata-sync --skip-hotspot-metadata-sync

# Migration with auto-tune and skip issue metadata sync
./cloudvoyager migrate -c migrate-config.json --verbose --auto-tune --skip-issue-metadata-sync

# Migration with auto-tune and skip hotspot metadata sync
./cloudvoyager migrate -c migrate-config.json --verbose --auto-tune --skip-hotspot-metadata-sync

# Migration with auto-tune, wait, and skip both metadata syncs
./cloudvoyager migrate -c migrate-config.json --verbose --wait --auto-tune --skip-issue-metadata-sync --skip-hotspot-metadata-sync

# Migration skipping quality profile sync (use default SonarQube Cloud profiles)
./cloudvoyager migrate -c migrate-config.json --verbose --skip-quality-profile-sync

# Migration skipping quality profile sync with auto-tune
./cloudvoyager migrate -c migrate-config.json --verbose --auto-tune --skip-quality-profile-sync

# Migration skipping quality profiles and all metadata syncs
./cloudvoyager migrate -c migrate-config.json --verbose --auto-tune --skip-issue-metadata-sync --skip-hotspot-metadata-sync --skip-quality-profile-sync

# Selective migration: only scan data (main branch)
./cloudvoyager migrate -c migrate-config.json --verbose --only scan-data

# Selective migration: only scan data (all branches)
./cloudvoyager migrate -c migrate-config.json --verbose --only scan-data-all-branches

# Selective migration: only quality gates
./cloudvoyager migrate -c migrate-config.json --verbose --only quality-gates

# Selective migration: only quality profiles
./cloudvoyager migrate -c migrate-config.json --verbose --only quality-profiles

# Selective migration: only permissions (groups + global + project)
./cloudvoyager migrate -c migrate-config.json --verbose --only permissions

# Selective migration: only permission templates
./cloudvoyager migrate -c migrate-config.json --verbose --only permission-templates

# Selective migration: only portfolios
./cloudvoyager migrate -c migrate-config.json --verbose --only portfolios

# Selective migration: only issue metadata
./cloudvoyager migrate -c migrate-config.json --verbose --only issue-metadata

# Selective migration: only hotspot metadata
./cloudvoyager migrate -c migrate-config.json --verbose --only hotspot-metadata

# Selective migration: only project settings
./cloudvoyager migrate -c migrate-config.json --verbose --only project-settings

# Selective migration: combine multiple components
./cloudvoyager migrate -c migrate-config.json --verbose --only scan-data,quality-gates,permissions

# Selective migration with auto-tune
./cloudvoyager migrate -c migrate-config.json --verbose --auto-tune --only scan-data-all-branches

# Selective migration with project concurrency
./cloudvoyager migrate -c migrate-config.json --verbose --project-concurrency 3 --only scan-data

# Resume a previously interrupted migration (automatic — just re-run)
./cloudvoyager migrate -c migrate-config.json --verbose

# Force restart migration from scratch (discard migration journal)
./cloudvoyager migrate -c migrate-config.json --verbose --force-restart

# Force release a stale lock from a crashed migration
./cloudvoyager migrate -c migrate-config.json --verbose --force-unlock

verify — Verify migration completeness by comparing SonarQube Server and SonarQube Cloud data

Flag Short Required Argument Description
--config <path> -c Yes File path Path to the migration configuration file
--verbose -v No Enable debug-level logging for detailed output
--only <components> No Comma-separated list Only verify specific components. Valid values: scan-data, scan-data-all-branches, portfolios, quality-gates, quality-profiles, permission-templates, permissions, issue-metadata, hotspot-metadata, project-settings
--output-dir <path> No Directory path Output directory for verification reports (default: ./verification-output)
--concurrency <n> No Integer Override the maximum concurrency for I/O operations
--max-memory <mb> No Integer Set the max heap size in MB; auto-restarts with increased heap if needed
--auto-tune No Auto-detect hardware and set optimal concurrency and memory values

Examples

# Verify all migration data
./cloudvoyager verify -c migrate-config.json

# Verify with verbose logging
./cloudvoyager verify -c migrate-config.json --verbose

# Verify with auto-tuned performance
./cloudvoyager verify -c migrate-config.json --verbose --auto-tune

# Verify only issue metadata
./cloudvoyager verify -c migrate-config.json --verbose --only issue-metadata

# Verify only hotspot metadata
./cloudvoyager verify -c migrate-config.json --verbose --only hotspot-metadata

# Verify only scan data (branches + measures)
./cloudvoyager verify -c migrate-config.json --verbose --only scan-data

# Verify only quality gates
./cloudvoyager verify -c migrate-config.json --verbose --only quality-gates

# Verify only quality profiles
./cloudvoyager verify -c migrate-config.json --verbose --only quality-profiles

# Verify only permissions (groups + global + project)
./cloudvoyager verify -c migrate-config.json --verbose --only permissions

# Verify only project settings
./cloudvoyager verify -c migrate-config.json --verbose --only project-settings

# Verify multiple components
./cloudvoyager verify -c migrate-config.json --verbose --only issue-metadata,hotspot-metadata,quality-gates

# Verify with custom output directory
./cloudvoyager verify -c migrate-config.json --verbose --output-dir ./my-verification

# Verify with custom concurrency
./cloudvoyager verify -c migrate-config.json --verbose --concurrency 8

# Verify with auto-tune and max-memory override
./cloudvoyager verify -c migrate-config.json --verbose --auto-tune --max-memory 8192

sync-metadata — Sync issue and hotspot metadata for already-migrated projects

Flag Short Required Argument Description
--config <path> -c Yes File path Path to the migration configuration file
--verbose -v No Enable debug-level logging for detailed output
--skip-issue-metadata-sync No Skip syncing issue metadata (statuses, assignments, comments, tags); only sync hotspot metadata
--skip-hotspot-metadata-sync No Skip syncing hotspot metadata (statuses, comments); only sync issue metadata
--skip-quality-profile-sync No Skip syncing quality profiles (projects use default SonarQube Cloud profiles)
--concurrency <n> No Integer Override the maximum concurrency for I/O operations (issue sync, hotspot sync, hotspot extraction)
--max-memory <mb> No Integer Set the max heap size in MB; auto-restarts with increased heap if needed
--auto-tune No Auto-detect hardware and set optimal concurrency and memory values
--skip-all-branch-sync No Only sync the main branch of each project (skip non-main branches). Equivalent to setting transfer.syncAllBranches: false in config

Examples

# Sync all metadata (issues + hotspots)
./cloudvoyager sync-metadata -c migrate-config.json

# Sync all metadata with verbose logging
./cloudvoyager sync-metadata -c migrate-config.json --verbose

# Sync only issue metadata (skip hotspots)
./cloudvoyager sync-metadata -c migrate-config.json --skip-hotspot-metadata-sync

# Sync only issue metadata with verbose logging
./cloudvoyager sync-metadata -c migrate-config.json --verbose --skip-hotspot-metadata-sync

# Sync only hotspot metadata (skip issues)
./cloudvoyager sync-metadata -c migrate-config.json --skip-issue-metadata-sync

# Sync only hotspot metadata with verbose logging
./cloudvoyager sync-metadata -c migrate-config.json --verbose --skip-issue-metadata-sync

# Sync metadata with custom I/O concurrency
./cloudvoyager sync-metadata -c migrate-config.json --concurrency 8

# Sync metadata with verbose logging and custom I/O concurrency
./cloudvoyager sync-metadata -c migrate-config.json --verbose --concurrency 8

# Sync metadata with custom max memory
./cloudvoyager sync-metadata -c migrate-config.json --max-memory 4096

# Sync metadata with verbose logging and custom max memory
./cloudvoyager sync-metadata -c migrate-config.json --verbose --max-memory 4096

# Sync metadata with auto-tuned settings
./cloudvoyager sync-metadata -c migrate-config.json --auto-tune

# Sync metadata with verbose logging and auto-tune
./cloudvoyager sync-metadata -c migrate-config.json --verbose --auto-tune

# Sync only issues with custom concurrency
./cloudvoyager sync-metadata -c migrate-config.json --verbose --concurrency 8 --skip-hotspot-metadata-sync

# Sync only hotspots with custom concurrency
./cloudvoyager sync-metadata -c migrate-config.json --verbose --concurrency 8 --skip-issue-metadata-sync

# Sync only issues with auto-tune
./cloudvoyager sync-metadata -c migrate-config.json --verbose --auto-tune --skip-hotspot-metadata-sync

# Sync only hotspots with auto-tune
./cloudvoyager sync-metadata -c migrate-config.json --verbose --auto-tune --skip-issue-metadata-sync

# Sync metadata with all manual performance flags
./cloudvoyager sync-metadata -c migrate-config.json --verbose --concurrency 8 --max-memory 4096

# Sync metadata with auto-tune and max-memory override
./cloudvoyager sync-metadata -c migrate-config.json --verbose --auto-tune --max-memory 8192

# Sync only issues with all manual performance flags
./cloudvoyager sync-metadata -c migrate-config.json --verbose --concurrency 8 --max-memory 4096 --skip-hotspot-metadata-sync

# Sync only hotspots with all manual performance flags
./cloudvoyager sync-metadata -c migrate-config.json --verbose --concurrency 8 --max-memory 4096 --skip-issue-metadata-sync

🧹 Linting

# Check for lint errors
npm run lint

# Auto-fix lint errors
npm run lint:fix

ESLint configuration (v8.56.0): ES2021, Node.js environment, 2-space indent, Unix linebreaks, single quotes, semicolons required. console is allowed (CLI tool).


🧪 Running Tests

# Run tests with coverage
npm test

# Run tests without coverage (faster)
npm run test:fast

Test Configuration

  • Test runner: AVA v6.4.1
  • Test glob: test/**/*.test.js (50+ test files)
  • Timeout: 60 seconds per test
  • Concurrency: 4 parallel test workers
  • ESM mocking: Uses esmock v2.7.3 loader for mocking ES modules
  • Stub library: sinon v21.0.1
  • Coverage: c8 v10.1.3, generates lcov + text reports to coverage/
  • Coverage includes: src/**/*.js (excludes protobuf/schema/**)

🏗️ CI/CD (GitHub Actions)

The project uses a multi-stage GitHub Actions pipeline:

Workflow Purpose Details
install.yml Install dependencies Node.js 18, npm ci, caches node_modules
build.yml Build CLI binaries 6 platform builds in parallel using Node.js 20
build-desktop.yml Build Electron desktop apps 6 Electron builds (depends on CLI build artifacts)
release.yml Orchestrator Chains: install → build → build-desktop → release
sonarcloud.yml SonarQube Cloud SAST/SCA Automatic scanning on push to main and on PRs. Requires SONAR_TOKEN secret
gh-release.yml GitHub Releases Creates releases with milestone links derived from version tags

SonarQube Cloud Scanning

The repository includes a sonarcloud.yml workflow and a sonar-project.properties file at the project root for automatic SAST/SCA scanning via SonarQube Cloud. The workflow runs on every push to main and on pull requests. It requires a SONAR_TOKEN secret configured in the GitHub repository settings.

Platform Build Matrix (6 targets)

Platform Runner
linux-x64 ubuntu-latest
linux-arm64 ubuntu-24.04-arm
macos-arm64 macos-latest (native)
macos-x64 macos-latest (cross-compile)
win-x64 windows-latest
win-arm64 windows-11-arm

🌍 Environment Variables

Variable Description
LOG_LEVEL Set logging level: debug, info, warn, error
LOG_FILE Path to log file (optional, logs to console by default)
SONARQUBE_TOKEN Override SonarQube Server token from config
SONARCLOUD_TOKEN Override SonarQube Cloud token from config
SONARQUBE_URL Override SonarQube Server URL from config
SONARCLOUD_URL Override SonarQube Cloud URL from config
MAX_SOURCE_FILES Limit number of source files to extract (0 = all)

Examples with environment variables

# Run with debug logging to a file
LOG_LEVEL=debug LOG_FILE=./cloudvoyager.log ./cloudvoyager migrate -c migrate-config.json --verbose

# Override tokens via environment
SONARQUBE_TOKEN=sqp_xxx SONARCLOUD_TOKEN=sqa_yyy ./cloudvoyager transfer -c config.json --verbose

# Limit source files for testing
MAX_SOURCE_FILES=10 ./cloudvoyager transfer -c config.json --verbose

⚡ npm Scripts

The following npm scripts are available for building, testing, and linting:

What it does npm script
Run CLI (no arguments) npm start
Install dependencies npm install
Bundle JavaScript only npm run build
Build binary for current platform (Node.js SEA) npm run package
Build binary via Bun (experimental) npm run package:bun
Cross-compile via Bun (experimental) npm run package:bun:cross
Run tests with coverage npm test
Run tests (no coverage) npm run test:fast
Lint npm run lint
Lint with auto-fix npm run lint:fix
Validate config npm run validate
Test connections npm run test:connection
Check sync status npm run status
Reset state npm run reset
Transfer single project npm run transfer
Transfer single project (auto-tune) npm run transfer:auto-tune
Show transfer checkpoint progress npm run transfer:show-progress
Full migration npm run migrate
Full migration (dry-run) npm run migrate:dry-run
Full migration (auto-tune) npm run migrate:auto-tune
Migration, skip issue metadata npm run migrate:skip-issue-metadata
Migration, skip hotspot metadata npm run migrate:skip-hotspot-metadata
Migration, skip all metadata npm run migrate:skip-all-metadata
Migration, skip all metadata (auto-tune) npm run migrate:skip-all-metadata:auto-tune
Migration, skip quality profiles npm run migrate:skip-quality-profiles
Migration, skip quality profiles (auto-tune) npm run migrate:skip-quality-profiles:auto-tune
Migration, skip all (metadata + profiles, auto-tuned) npm run migrate:skip-all
Migration, only scan data (main branch) npm run migrate:only-scan-data
Migration, only scan data (all branches) npm run migrate:only-scan-data-all-branches
Migration, only quality gates npm run migrate:only-quality-gates
Migration, only quality profiles npm run migrate:only-quality-profiles
Migration, only permissions npm run migrate:only-permissions
Migration, only permission templates npm run migrate:only-permission-templates
Migration, only portfolios npm run migrate:only-portfolios
Migration, only issue metadata npm run migrate:only-issue-metadata
Migration, only hotspot metadata npm run migrate:only-hotspot-metadata
Migration, only project settings npm run migrate:only-project-settings
Sync metadata (issues + hotspots) npm run sync-metadata
Sync metadata (auto-tune) npm run sync-metadata:auto-tune
Sync metadata, skip issue metadata npm run sync-metadata:skip-issue-metadata
Sync metadata, skip hotspot metadata npm run sync-metadata:skip-hotspot-metadata
Sync metadata, skip quality profiles npm run sync-metadata:skip-quality-profiles
Verify migration completeness npm run verify
Verify migration (auto-tuned) npm run verify:auto-tune
Verify only scan data npm run verify:only-scan-data
Verify only scan data (all branches) npm run verify:only-scan-data-all-branches
Verify only issue metadata npm run verify:only-issue-metadata
Verify only hotspot metadata npm run verify:only-hotspot-metadata
Verify only quality gates npm run verify:only-quality-gates
Verify only quality profiles npm run verify:only-quality-profiles
Verify only permissions npm run verify:only-permissions
Verify only project settings npm run verify:only-project-settings

Note: Always use the built binary to run CloudVoyager commands (e.g. ./cloudvoyager migrate -c ...). See the CLI Reference section for all available commands and flags.


🐛 Debugging Scripts

The .debugging/ folder contains convenience scripts for local testing:

Script What it does
test-migrate.sh Run migrate command with migrate-config.json
test-transfer.sh Run transfer command with transfer-config.json
test-verify.sh Run verify command with migrate-config.json
build-desktop.sh Build the Electron desktop app
run-desktop.sh Launch the desktop app in dev mode
delete-all-sonarcloud-projects.sh Delete all projects from a SonarQube Cloud org (for cleanup)

These scripts expect the binary at ./dist/bin/cloudvoyager-macos-arm64 and config files at the repo root. Both migrate-config.json and transfer-config.json are gitignored since they contain credentials.


📚 Further Reading


🧪 Regression Testing

The regression testing system validates that bug fixes and behavioral changes in CloudVoyager remain correct across SonarQube Server versions.

Where the Code Lives

  • Assertion scripts and helpers: test/regression/ in this repository contains the assertion scripts (assert-*.js), shared helpers, and enrichment scripts used by regression tests.
  • CI workflow: The actual CI pipeline that orchestrates regression runs lives in the private repo sonar-solutions/cloudvoyager-ci (not this public repo). The workflow file is regression-bug-fixes.yml.

Running Regression Tests Locally

Full regression tests require an environment that mirrors CI:

  1. Docker — ephemeral SonarQube Server containers are spun up per test scenario.
  2. SonarQube Server Enterprise license key — the containers need a valid Enterprise Edition license.
  3. SonarQube Cloud organization access — tests migrate data into SonarQube Cloud and verify the results.

Note: These prerequisites make local runs heavyweight. Most day-to-day development does not require running the full regression suite locally — CI handles it on every PR.

Meta-Tests (No Docker Required)

The helper utilities in test/regression/helpers/ have their own unit tests (test/regression/helpers/*.test.js). These meta-tests run with the regular test command and do not require Docker or a running SonarQube Server instance:

npm test

Adding a New Regression Test

  1. Create an assertion script: Add test/regression/assert-{scenario-name}.js in this repository. Follow the conventions of existing assertion scripts in the same directory.
  2. Add a matrix entry: In the private repo sonar-solutions/cloudvoyager-ci, add a new entry to the matrix in regression-bug-fixes.yml that references your assertion script and the SonarQube Server version(s) it should run against.