Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 47 additions & 6 deletions .github/workflows/update-cli.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,56 @@ jobs:
run: |
echo ${{ steps.checkmarx-ast-cli.outputs.release_tag }} > checkmarx-ast-cli.version

# Update the TypeScript file's cliDefaultVersion field
- name: Update cliDefaultVersion in CxInstaller.ts
# Download CLI binaries and generate checksums
- name: Download CLI and generate checksums
if: steps.checkmarx-ast-cli.outputs.current_tag != steps.checkmarx-ast-cli.outputs.release_tag
env:
NEW_CLI_VERSION: ${{ steps.checkmarx-ast-cli.outputs.release_tag }}
RELEASE_TAG: ${{ steps.checkmarx-ast-cli.outputs.release_tag }}
run: |
FILE_PATH="src/main/osinstaller/CxInstaller.ts"
# Ensure that 'cliDefaultVersion' is updated correctly
sed -i "s/\(cliDefaultVersion = '\)[^']*\(';\)/\1${NEW_CLI_VERSION}\2/" $FILE_PATH
VERSION=$RELEASE_TAG

# Initialize checksums object
CHECKSUMS='{}'

# Platform configurations: platform_name,architecture,extension,os_platform
PLATFORMS=(
"windows,x64,zip,windows"
"darwin,x64,tar.gz,darwin"
"linux,x64,tar.gz,linux"
"linux,arm64,tar.gz,linux"
"linux,armv6,tar.gz,linux"
)

for PLATFORM_CONFIG in "${PLATFORMS[@]}"; do
IFS=',' read -r OS_TYPE ARCH EXT OS_PLATFORM <<< "$PLATFORM_CONFIG"

KEY="${OS_PLATFORM}_${ARCH}"
URL="https://download.checkmarx.com/CxOne/CLI/${VERSION}/ast-cli_${VERSION}_${OS_PLATFORM}_${ARCH}.${EXT}"

echo "Downloading checksum for ${KEY} from ${URL}..."

# Download binary
TEMP_FILE="/tmp/ast-cli_${KEY}.${EXT}"
if curl -sL -o "$TEMP_FILE" "$URL"; then
# Calculate SHA-256
CHECKSUM=$(sha256sum "$TEMP_FILE" | awk '{print $1}')
echo "✓ ${KEY}: ${CHECKSUM}"

# Update checksums JSON
CHECKSUMS=$(echo "$CHECKSUMS" | jq --arg key "$KEY" --arg value "$CHECKSUM" '.[$key] = $value')

# Cleanup
rm -f "$TEMP_FILE"
else
echo "✗ Failed to download ${KEY}"
exit 1
fi
done

# Write checksums to file
echo "$CHECKSUMS" | jq '.' > checkmarx-ast-cli.checksums
echo "Checksums updated:"
cat checkmarx-ast-cli.checksums

# Create a Pull Request with the version changes
- name: Create Pull Request
Expand Down
40 changes: 14 additions & 26 deletions src/main/osinstaller/CxInstaller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,6 @@ export class CxInstaller {
linux: { platform: linuxOS, extension: 'tar.gz' }
};

// Default version and its paired SHA-256 checksums, keyed by "platform_architecture".
// Update both together when bumping the default CLI version.
private readonly cliDefaultVersion = '2.3.48';
private static readonly cliDefaultChecksums: Record<string, string> = {
'windows_x64': '441ee8df46cc630ae000f8ba73925113aeed8c4d16cf274944aff3e7197e3470',
'darwin_x64': 'b72f7e4ca14e5e56600b07d22c848a4b85e7c37d2e595424340cc699ea10006b',
'linux_x64': 'eb3eb55add37f150188f5a8b36b2a659f902ad9569dcb7ee652531fe525022e2',
'linux_arm64': '7df61689b3c2bbd4c27face5bdc0da97f63e4533229d6b53dd777f90d3904931',
'linux_armv6': '99659f2e0804b197550efc6a9ddb6029babc980d32bdfeeb508199247ac95878'
};

constructor(platform: string, client: AstClient) {
this.platform = platform as SupportedPlatforms;
Expand All @@ -50,8 +40,7 @@ export class CxInstaller {
}

// Returns the CLI version and its platform-specific SHA-256 checksum.
// Tries the version file and checksums file first; falls back to the
// hardcoded defaults if the version file is absent or empty.
// Reads from version and checksums files. Throws CxError if version is absent or version file is empty.
// Result is cached after the first read.
async readASTCLIVersion(): Promise<{ version: string; checksum: string | null }> {
if (this.cliVersion) {
Expand All @@ -68,24 +57,23 @@ export class CxInstaller {
const trimmed = content.trim();
if (trimmed) version = trimmed;
} catch {
// version file absent — fall through to defaults
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we have empty catch block ?

// version file absent — will throw error below
}

let checksum: string | null;
if (version === null) {
version = this.cliDefaultVersion;
checksum = CxInstaller.cliDefaultChecksums[key] ?? null;
} else {
try {
const content = await fsPromises.readFile(this.getChecksumsFilePath(), 'utf-8');
checksum = (JSON.parse(content) as Record<string, string>)[key] ?? null;
if (checksum === null) {
logger.warn(`No checksum found for ${key} in checksums file. Download will not be verified.`);
}
} catch {
logger.warn(`Checksums file not found. Download of version ${version} will not be verified.`);
checksum = null;
throw new CxError(`CLI version not found`);
}

let checksum: string | null;
try {
const content = await fsPromises.readFile(this.getChecksumsFilePath(), 'utf-8');
checksum = (JSON.parse(content) as Record<string, string>)[key] ?? null;
if (checksum === null) {
logger.warn(`No checksum found for ${key} in checksums file. Download will not be verified.`);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should throw an exception here. Valid checksum is not found.

}
} catch {
logger.warn(`Checksums file not found. Download of version ${version} will not be verified.`);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here also throw an exception

checksum = null;
}

this.cliVersion = version;
Expand Down
15 changes: 9 additions & 6 deletions src/tests/CxInstallerTest.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,27 @@ const cxInstallerWindows = new CxInstaller("win32", astClientInstance);

describe("CxInstaller cases", () => {
it('CxInstaller getDownloadURL Linux Successful case', async () => {
const testVersion = '2.3.48';
jest.spyOn(cxInstallerLinux as any, 'readASTCLIVersion').mockResolvedValue({ version: testVersion, checksum: null });
const { url } = await cxInstallerLinux.getDownloadURL();
const { version } = await cxInstallerLinux.readASTCLIVersion();
const architecture = getArchitecture(cxInstallerLinux.getPlatform());
expect(url).toBe(`https://download.checkmarx.com/CxOne/CLI/${version}/ast-cli_${version}_linux_${architecture}.tar.gz`);
expect(url).toBe(`https://download.checkmarx.com/CxOne/CLI/${testVersion}/ast-cli_${testVersion}_linux_${architecture}.tar.gz`);
});

it('CxInstaller getDownloadURL Mac Successful case', async () => {
const testVersion = '2.3.48';
jest.spyOn(cxInstallerMac as any, 'readASTCLIVersion').mockResolvedValue({ version: testVersion, checksum: null });
const { url } = await cxInstallerMac.getDownloadURL();
const { version } = await cxInstallerLinux.readASTCLIVersion();
const architecture = getArchitecture(cxInstallerMac.getPlatform());
expect(url).toBe(`https://download.checkmarx.com/CxOne/CLI/${version}/ast-cli_${version}_darwin_${architecture}.tar.gz`);
expect(url).toBe(`https://download.checkmarx.com/CxOne/CLI/${testVersion}/ast-cli_${testVersion}_darwin_${architecture}.tar.gz`);
});

it('CxInstaller getDownloadURL Windows Successful case', async () => {
const testVersion = '2.3.48';
jest.spyOn(cxInstallerWindows as any, 'readASTCLIVersion').mockResolvedValue({ version: testVersion, checksum: null });
const { url } = await cxInstallerWindows.getDownloadURL();
const { version } = await cxInstallerLinux.readASTCLIVersion();
const architecture = getArchitecture(cxInstallerWindows.getPlatform());
expect(url).toBe(`https://download.checkmarx.com/CxOne/CLI/${version}/ast-cli_${version}_windows_${architecture}.zip`);
expect(url).toBe(`https://download.checkmarx.com/CxOne/CLI/${testVersion}/ast-cli_${testVersion}_windows_${architecture}.zip`);
});
});

Expand Down
Loading