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
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,12 @@ $(BINARY_WRAPPER_DIR)/src/generated/version: $(BINARY_WRAPPER_DIR)/src/generated
$(BINARY_WRAPPER_DIR)/src/generated/sha256sums.txt:
@echo "-- Generating $(@F)"
@cat $(BINARY_OUTPUT_FOLDER)/*.sha256 > $(BINARY_WRAPPER_DIR)/src/generated/sha256sums.txt
@for f in $(BINARY_OUTPUT_FOLDER)/experimental/*.sha256; do \
sed "s| \(.*\)| experimental/\1|" "$$f"; \
done >> $(BINARY_WRAPPER_DIR)/src/generated/sha256sums.txt

.PHONY: build-binary-wrapper
build-binary-wrapper: pre-build-binary-wrapper $(BINARY_WRAPPER_DIR)/src/generated/version $(BINARY_WRAPPER_DIR)/src/generated/sha256sums.txt
build-binary-wrapper: pre-build-binary-wrapper $(BINARY_WRAPPER_DIR)/src/generated/version $(BINARY_WRAPPER_DIR)/src/generated/sha256sums.txt $(BINARY_RELEASES_FOLDER_TS_CLI)/experimental/snyk-linux $(BINARY_RELEASES_FOLDER_TS_CLI)/experimental/snyk-linux-arm64
@echo "-- Building Typescript Binary Wrapper ($(BINARY_WRAPPER_DIR)/dist/)"
@cd $(BINARY_WRAPPER_DIR); npm run build

Expand Down
4 changes: 4 additions & 0 deletions binary-deployments.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,9 @@
"linux": {
"amd64": "snyk-linux",
"arm64": "snyk-linux-arm64"
},
"linuxstatic": {
"amd64": "experimental/snyk-linux",
"arm64": "experimental/snyk-linux-arm64"
}
}
103 changes: 64 additions & 39 deletions scripts/build-ts-binary-wrapper-locally.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,22 @@ const (
nc = "\033[0m" // No Color
)

// Configuration
/*
Parameters can be retrieved from https://github.com/snyk/cli/releases
* version: the version of the snyk binary to download
* platform: the platform of the snyk binary to download
* sha256Hash: the sha256 hash of the snyk binary to download

Linux static specific parameters are optional and only used when building for linux static targets
* linuxstaticPlatform: the linux static platform of the snyk binary to download [snyk-linux, snyk-linux-arm64]
* linuxstaticSha256Hash: the sha256 hash of the linuxstatic snyk binary to download. Retrieved from http://downloads.snyk.io/experimental/cli/<version>/<linuxstaticPlatform>.sha256
*/
const (
version = "1.1298.2"
platform = "snyk-macos-arm64"
sha256Hash = "0a5016d8ec007483fc3397ea06c4f655a3771c3bee34fb778b8bb12c5b19ed9a"
version = "1.1304.2"
platform = "snyk-linux-arm64"
sha256Hash = "79391210b25e50297db2cec379ccf5ed16f484ce16076195c323c26a05c63d1c"
linuxstaticPlatform = "snyk-linux-arm64"
linuxstaticSha256Hash = "7bc078339b4db675f4009257c0cb97713ff8e0c63add204200509832e3ad98b0"
)

// Logging functions
Expand All @@ -49,26 +60,26 @@ func getProjectRoot() (string, error) {
if err != nil {
return "", err
}

// Check if we're in the scripts directory
if filepath.Base(scriptDir) == "scripts" {
return filepath.Dir(scriptDir), nil
}

// If not, try to find the project root by looking for key files
currentDir, err := os.Getwd()
if err != nil {
return "", fmt.Errorf("failed to get current directory: %w", err)
}

// Walk up the directory tree to find the project root
for dir := currentDir; dir != filepath.Dir(dir); dir = filepath.Dir(dir) {
if fileExists(filepath.Join(dir, "package.json")) &&
fileExists(filepath.Join(dir, "Makefile")) {
if fileExists(filepath.Join(dir, "package.json")) &&
fileExists(filepath.Join(dir, "Makefile")) {
return dir, nil
}
}

return "", fmt.Errorf("could not find project root (no package.json and Makefile found)")
}

Expand All @@ -82,19 +93,19 @@ func getScriptDir() (string, error) {
}
return filepath.Dir(filename), nil
}

// If running as compiled binary, use os.Executable
executable, err := os.Executable()
if err != nil {
return "", fmt.Errorf("failed to get executable path: %w", err)
}

// Resolve symlinks to get the actual path
resolvedPath, err := filepath.EvalSymlinks(executable)
if err != nil {
return "", fmt.Errorf("failed to resolve symlinks: %w", err)
}

return filepath.Dir(resolvedPath), nil
}

Expand All @@ -119,35 +130,35 @@ func dirExists(path string) bool {
// Function to check if required tools are available
func checkRequirements(projectRoot string) error {
logInfo("Checking requirements...")

if !isCommandAvailable("npm") {
return fmt.Errorf("npm is not installed or not in PATH")
}

if !isCommandAvailable("make") {
return fmt.Errorf("make is not installed or not in PATH")
}

if !fileExists(filepath.Join(projectRoot, "package.json")) {
return fmt.Errorf("package.json not found in project root")
}

if !fileExists(filepath.Join(projectRoot, "Makefile")) {
return fmt.Errorf("Makefile not found in project root")
}

logSuccess("All requirements satisfied")
return nil
}

// Function to validate the project structure
func validateProject(projectRoot string) error {
logInfo("Validating project structure...")

if !dirExists(projectRoot) {
return fmt.Errorf("project root directory not found: %s", projectRoot)
}

logSuccess("Project structure validated")
return nil
}
Expand All @@ -157,105 +168,119 @@ func runCommand(name string, args ...string) error {
cmd := exec.Command(name, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr

logInfo(fmt.Sprintf("Running: %s %s", name, strings.Join(args, " ")))

if err := cmd.Run(); err != nil {
return fmt.Errorf("command failed: %w", err)
}

return nil
}

// Write content to a file
func writeFile(path, content string) error {
logInfo(fmt.Sprintf("Creating file: %s", path))

if err := os.WriteFile(path, []byte(content), 0644); err != nil {
return fmt.Errorf("failed to write file %s: %w", path, err)
}

return nil
}

// Create directory if it doesn't exist
func createDir(path string) error {
logInfo(fmt.Sprintf("Creating directory: %s", path))

if err := os.MkdirAll(path, 0755); err != nil {
return fmt.Errorf("failed to create directory %s: %w", path, err)
}

return nil
}

// Main execution
func main() {
logInfo("Starting build process...")
logWarning(fmt.Sprintf("This script assumes %s, please change it if needed!", platform))
logWarning(fmt.Sprintf("This script assumes %s (linuxstatic: %s), please change it if needed!", platform, linuxstaticPlatform))

// Get project root
projectRoot, err := getProjectRoot()
if err != nil {
logError(fmt.Sprintf("Failed to get project root: %v", err))
os.Exit(1)
}

logInfo(fmt.Sprintf("Project root determined: %s", projectRoot))

// Validate environment
if err := validateProject(projectRoot); err != nil {
logError(err.Error())
os.Exit(1)
}

if err := checkRequirements(projectRoot); err != nil {
logError(err.Error())
os.Exit(1)
}

// Change to project root directory
logInfo(fmt.Sprintf("Changing to project root: %s", projectRoot))
if err := os.Chdir(projectRoot); err != nil {
logError(fmt.Sprintf("Failed to change directory: %v", err))
os.Exit(1)
}

// Install dependencies
logInfo("Installing npm dependencies...")
if err := runCommand("npm", "ci"); err != nil {
logError("Failed to install dependencies")
os.Exit(1)
}
logSuccess("Dependencies installed successfully")

// Create binary-releases directory
binaryReleasesDir := "binary-releases"
if err := createDir(binaryReleasesDir); err != nil {
logError(err.Error())
os.Exit(1)
}

// Create version file
versionFile := filepath.Join(binaryReleasesDir, "version")
if err := writeFile(versionFile, version); err != nil {
logError(err.Error())
os.Exit(1)
}

// Create SHA256 file
sha256File := filepath.Join(binaryReleasesDir, platform+".sha256")
sha256Content := fmt.Sprintf("%s %s", sha256Hash, platform)
if err := writeFile(sha256File, sha256Content); err != nil {
logError(err.Error())
os.Exit(1)
}


// Create experimental directory and linuxstatic SHA256 file
experimentalDir := filepath.Join(binaryReleasesDir, "experimental")
if err := createDir(experimentalDir); err != nil {
logError(err.Error())
os.Exit(1)
}

sha256File2 := filepath.Join(experimentalDir, linuxstaticPlatform+".sha256")
sha256Content2 := fmt.Sprintf("%s %s", linuxstaticSha256Hash, linuxstaticPlatform)
if err := writeFile(sha256File2, sha256Content2); err != nil {
logError(err.Error())
os.Exit(1)
}

// Build the binary
logInfo("Building binary release...")
if err := runCommand("make", "binary-releases/snyk.tgz"); err != nil {
logError("Binary build failed")
os.Exit(1)
}
logSuccess("Binary build completed successfully")
}
}
43 changes: 32 additions & 11 deletions ts-binary-wrapper/src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,16 @@ export const integrationName = 'TS_BINARY_WRAPPER';
export class WrapperConfiguration {
private version: string;
private binaryName: string;
private expectedSha256sum: string;
private expectedSha256sums: string[];

public constructor(
version: string,
binaryName: string,
expectedSha256sum: string,
expectedSha256sums: string[],
) {
this.version = version;
this.binaryName = binaryName;
this.expectedSha256sum = expectedSha256sum;
this.expectedSha256sums = expectedSha256sums;
}

public getVersion(): string {
Expand All @@ -61,8 +61,8 @@ export class WrapperConfiguration {
return path.join(currentFolder, this.binaryName);
}

public getShasumFile(): string {
return this.expectedSha256sum;
public getShasumFile(): string[] {
return this.expectedSha256sums;
}
}

Expand Down Expand Up @@ -150,8 +150,28 @@ export function getCurrentSha256sum(
export function getCurrentConfiguration(): WrapperConfiguration {
const binaryName = determineBinaryName(os.platform(), os.arch());
const version = getCurrentVersion(versionFile);
const expectedSha256sum = getCurrentSha256sum(binaryName, shasumFile);
return new WrapperConfiguration(version, binaryName, expectedSha256sum);
const expectedSha256sums: string[] = [
getCurrentSha256sum(binaryName, shasumFile),
];

const supportedPlatforms = require(binaryDeploymentsFilePath);
const linuxstaticPlatform = supportedPlatforms['linuxstatic'];
if (linuxstaticPlatform) {
const archname =
os.arch() === 'x64' || os.arch() === 'amd64' ? 'amd64' : os.arch();
const linuxstaticBinaryName = linuxstaticPlatform[archname];
if (linuxstaticBinaryName && linuxstaticBinaryName !== binaryName) {
const linuxstaticShasum = getCurrentSha256sum(
linuxstaticBinaryName,
shasumFile,
);
if (!linuxstaticShasum.startsWith('unknown-shasum-')) {
expectedSha256sums.push(linuxstaticShasum);
}
}
}

return new WrapperConfiguration(version, binaryName, expectedSha256sums);
}

export function getCliArguments(inputArgv: string[]): string[] {
Expand Down Expand Up @@ -255,14 +275,15 @@ export function formatErrorMessage(message: string): boolean {
export function downloadExecutable(
downloadUrl: string,
filename: string,
filenameShasum: string,
filenameShasum: string[],
): Promise<Error | undefined> {
return new Promise<Error | undefined>(function (resolve) {
logErrorWithTimeStamps('Starting download');
const options = new URL(`${downloadUrl}?utm_source=${integrationName}`);
const temp = path.join(__dirname, Date.now().toString());
const fileStream = fs.createWriteStream(temp);
const shasum = createHash('sha256').setEncoding('hex');
const expectedShasums = filenameShasum;

const cleanupAfterError = (error: Error) => {
try {
Expand All @@ -283,9 +304,9 @@ export function downloadExecutable(
'Shasums:\n- actual: ' +
actualShasum +
'\n- expected: ' +
filenameShasum;
expectedShasums.join(' or ');

if (filenameShasum && actualShasum != filenameShasum) {
if (expectedShasums.some(Boolean) && !expectedShasums.includes(actualShasum)) {
cleanupAfterError(Error('Shasum comparison failed!\n' + debugMessage));
} else {
logErrorWithTimeStamps(debugMessage);
Expand Down Expand Up @@ -343,7 +364,7 @@ export async function downloadWithBackup(
downloadUrl: string,
backupUrl: string,
filename: string,
filenameShasum: string,
filenameShasum: string[],
): Promise<Error | undefined> {
try {
const error = await downloadExecutable(
Expand Down
Loading
Loading