Skip to content

Commit

Permalink
feat: added Dockerfile support
Browse files Browse the repository at this point in the history
Signed-off-by: Ilona Shishov <[email protected]>
  • Loading branch information
IlonaShishov committed Apr 4, 2024
1 parent 08da011 commit b3ba601
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/componentAnalysis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ class AnalysisResponse implements IAnalysisResponse {

/**
* Performs RHDA component analysis on provided manifest contents and fileType based on ecosystem.
* @param fileType - The type of file (e.g., 'pom.xml', 'package.json', 'go.mod', 'requirements.txt').
* @param fileType - The type of file (e.g., 'pom.xml', 'package.json', 'go.mod', 'requirements.txt', 'Dockerfile').
* @param contents - The contents of the manifest file to analyze.
* @returns A Promise resolving to an AnalysisResponse object.
*/
Expand Down
5 changes: 5 additions & 0 deletions src/fileHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { DependencyProvider as PackageJson } from './providers/package.json';
import { DependencyProvider as PomXml } from './providers/pom.xml';
import { DependencyProvider as GoMod } from './providers/go.mod';
import { DependencyProvider as RequirementsTxt } from './providers/requirements.txt';
import { DependencyProvider as Dockerfile } from './providers/dockerfile';

/**
* Describes the available event streams.
Expand Down Expand Up @@ -118,6 +119,10 @@ files.on(EventStream.Diagnostics, '^requirements\\.txt$', (uri, contents) => {
performDiagnostics(uri, contents, new RequirementsTxt());
});

files.on(EventStream.Diagnostics, '^Dockerfile$', (uri, contents) => {
performDiagnostics(uri, contents, new Dockerfile());
});

/**
* Describes the LSP server for analysis.
*/
Expand Down
102 changes: 102 additions & 0 deletions src/providers/dockerfile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Red Hat
* Licensed under the Apache-2.0 License. See License.txt in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';

import { IDependencyProvider, EcosystemDependencyResolver, IDependency, Dependency } from '../collector';

/**
* Process entries found in the Dockerfile file.
*/
export class DependencyProvider extends EcosystemDependencyResolver implements IDependencyProvider {

constructor() {
super('docker'); // set ecosystem to 'docker'
}

/**
* Parses the provided string as an array of lines.
* @param contents - The string content to parse into lines.
* @returns An array of strings representing lines from the provided content.
*/
private parseTxtDoc(contents: string): string[] {
return contents.split('\n');
}

private splitOnFirstOccurrence(input: string, delimiter: string): [string, string] {
const index = input.indexOf(delimiter);
if (index !== -1) {
const firstPart = input.substring(0, index);
const secondPart = input.substring(index + delimiter.length);
return [firstPart, secondPart];
} else {
return [input, ''];
}
}

/**
* Parses a line from the file and extracts dependency information.
* @param line - The line to parse for dependency information.
* @param index - The index of the line in the file.
* @returns An IDependency object representing the parsed dependency or null if no dependency is found.
*/
private parseLine(line: string, index: number): IDependency | null {
const match = line.match(/^\s*FROM\s+(.*)/);
if (match) {
let lineData = match[1];

// Remove the platform argument
lineData = lineData.replace(/--platform=[^\s]+/g, '');

// Remove the AS parameter
lineData = lineData.replace(/\s+AS\s+\S+/gi, '');

// Trim any extra spaces
lineData = lineData.trim();

// Split to name, version and digest
let data = this.splitOnFirstOccurrence(lineData, '@');
if (data[1] === '') {
data = this.splitOnFirstOccurrence(lineData, ':');
}

if (data[0] === 'scratch'){
return;
}

const depName: string = data[0];
const depVersion: string = data[1];

const dep = new Dependency ({ value: depName, position: { line: 0, column: 0 } });
dep.version = { value: depVersion, position: { line: index + 1, column: line.indexOf(depVersion ? depVersion : depName) + 1 } };
return dep;
}
return;
}

/**
* Extracts dependencies from lines parsed from the file.
* @param lines - An array of strings representing lines from the file.
* @returns An array of IDependency objects representing extracted dependencies.
*/
private extractDependenciesFromLines(lines: string[]): IDependency[] {
return lines.reduce((dependencies: IDependency[], line: string, index: number) => {
const parsedDependency = this.parseLine(line, index);
if (parsedDependency) {
dependencies.push(parsedDependency);
}
return dependencies;
}, []);
}

/**
* Collects dependencies from the provided manifest contents.
* @param contents - The manifest content to collect dependencies from.
* @returns A Promise resolving to an array of IDependency objects representing collected dependencies.
*/
async collect(contents: string): Promise<IDependency[]> {
const lines: string[] = this.parseTxtDoc(contents);
return this.extractDependenciesFromLines(lines);
}
}

0 comments on commit b3ba601

Please sign in to comment.