diff --git a/src/lib/plugins/rubygems/index.ts b/src/lib/plugins/rubygems/index.ts index efc284c7d5f..1b721ab1c31 100644 --- a/src/lib/plugins/rubygems/index.ts +++ b/src/lib/plugins/rubygems/index.ts @@ -48,5 +48,5 @@ async function gatherSpecs(root, targetFile): Promise { } } - throw new Error(`Could not handle file: ${targetFile}`); + throw new Error(`Could not handle rubygems file: ${targetFile}`); } diff --git a/src/lib/plugins/rubygems/inspectors/gemfile.ts b/src/lib/plugins/rubygems/inspectors/gemfile.ts index 3e1cb26582d..194f529c885 100644 --- a/src/lib/plugins/rubygems/inspectors/gemfile.ts +++ b/src/lib/plugins/rubygems/inspectors/gemfile.ts @@ -2,31 +2,42 @@ import * as path from 'path'; import { tryGetSpec } from './try-get-spec'; import { Spec } from './index'; -const pattern = /^Gemfile(\.lock)*$/; +/* Supported example patterns: + * Gemfile + * Gemfile.lock + * rails.2.4.5.gemfile + * rails.2.4.5.gemfile.lock + * gemfiles/Gemfile.rails-2.4.5.lock + * gemfiles/Gemfile.lock.rails-2.4.5 + */ + +const gemfileOrLockfilePattern = /.*[gG]emfile.*(\.lock)?.*$/; +const gemfileLockPattern = /.*[gG]emfile.*(\.lock).*$/; export function canHandle(file: string): boolean { - return !!file && pattern.test(path.basename(file)); + return !!file && gemfileOrLockfilePattern.test(path.basename(file)); } export async function gatherSpecs(root: string, target: string): Promise { - const targetName = path.basename(target); - const targetDir = path.dirname(target); - + const { dir, name } = path.parse(target); + const isGemfileLock = gemfileLockPattern.test(target); + // if the target is a Gemfile we treat is as the lockfile const gemfileLock = await tryGetSpec( root, - path.join(targetDir, 'Gemfile.lock'), + isGemfileLock ? target : path.join(dir, name + '.lock'), ); if (gemfileLock) { return { packageName: path.basename(root), - targetFile: path.join(targetDir, targetName), + targetFile: path.join(dir, name), files: { gemfileLock }, }; } else { throw new Error( - "Missing Gemfile.lock file: we can't test " + - 'without dependencies.\nPlease run `bundle install` first.', + `Could not read ${target || 'Gemfile.lock'} lockfile: can't test ` + + 'without dependencies.\nPlease run `bundle install` first or' + + ' if this is a custom file name re-run with --file=path/to/custom.gemfile.lock --package-manager=rubygems', ); } } diff --git a/src/lib/plugins/rubygems/inspectors/try-get-spec.ts b/src/lib/plugins/rubygems/inspectors/try-get-spec.ts index f2c566fd9bd..799b9c5dbcb 100644 --- a/src/lib/plugins/rubygems/inspectors/try-get-spec.ts +++ b/src/lib/plugins/rubygems/inspectors/try-get-spec.ts @@ -16,7 +16,6 @@ export async function tryGetSpec( name: string, ): Promise { const filePath = path.resolve(dir, name); - if (fs.existsSync(filePath)) { return { name, diff --git a/test/acceptance/cli-test/cli-test.ruby.spec.ts b/test/acceptance/cli-test/cli-test.ruby.spec.ts index 5c86cbb794d..c054b7c82ea 100644 --- a/test/acceptance/cli-test/cli-test.ruby.spec.ts +++ b/test/acceptance/cli-test/cli-test.ruby.spec.ts @@ -1,4 +1,3 @@ -import * as path from 'path'; import * as _ from '@snyk/lodash'; import { AcceptanceTests } from './cli-test.acceptance.test'; import { getWorkspaceJSON } from '../workspace-helper'; @@ -42,6 +41,80 @@ export const RubyTests: AcceptanceTests = { ); }, + '`test ruby-app-custom-names --file=123.gemfile.lock --package-manager=rubygems`': ( + params, + utils, + ) => async (t) => { + utils.chdirWorkspaces(); + await params.cli.test('ruby-app-custom-names', { + file: '123.gemfile.lock', + packageManager: 'rubygems', + }); + + const req = params.server.popRequest(); + t.equal(req.method, 'POST', 'makes POST request'); + t.equal( + req.headers['x-snyk-cli-version'], + params.versionNumber, + 'sends version number', + ); + t.match(req.url, '/test-dep-graph', 'posts to correct url'); + + const depGraph = req.body.depGraph; + t.equal(depGraph.pkgManager.name, 'rubygems'); + t.same( + depGraph.pkgs.map((p) => p.id).sort(), + [ + 'crass@1.0.4', + 'lynx@0.4.0', + 'mini_portile2@2.3.0', + 'nokogiri@1.8.5', + 'nokogumbo@1.5.0', + 'ruby-app-custom-names@', + 'sanitize@4.6.2', + 'yard@0.8.0', + ].sort(), + 'depGraph looks fine', + ); + }, + + '`test ruby-app-custom-names --file=gemfiles/Gemfile.rails-2.4.5.lock --package-manager=rubygems`': ( + params, + utils, + ) => async (t) => { + utils.chdirWorkspaces(); + await params.cli.test('ruby-app-custom-names', { + file: 'gemfiles/Gemfile.rails-2.4.5.lock', + packageManager: 'rubygems', + }); + + const req = params.server.popRequest(); + t.equal(req.method, 'POST', 'makes POST request'); + t.equal( + req.headers['x-snyk-cli-version'], + params.versionNumber, + 'sends version number', + ); + t.match(req.url, '/test-dep-graph', 'posts to correct url'); + + const depGraph = req.body.depGraph; + t.equal(depGraph.pkgManager.name, 'rubygems'); + t.same( + depGraph.pkgs.map((p) => p.id).sort(), + [ + 'crass@1.0.4', + 'lynx@0.4.0', + 'mini_portile2@2.3.0', + 'nokogiri@1.8.5', + 'nokogumbo@1.5.0', + 'ruby-app-custom-names@', + 'sanitize@4.6.2', + 'yard@0.8.0', + ].sort(), + 'depGraph looks fine', + ); + }, + '`test ruby-app` meta when no vulns': (params, utils) => async (t) => { utils.chdirWorkspaces(); const commandResult: CommandResult = await params.cli.test('ruby-app'); diff --git a/test/acceptance/workspaces/ruby-app-custom-names/123.gemfile b/test/acceptance/workspaces/ruby-app-custom-names/123.gemfile new file mode 100644 index 00000000000..88d27cc9f0c --- /dev/null +++ b/test/acceptance/workspaces/ruby-app-custom-names/123.gemfile @@ -0,0 +1,5 @@ +source :rubygems + +gem "sanitize", "4.6.2" +gem "yard", "0.8.0" +gem "lynx", "0.4.0" diff --git a/test/acceptance/workspaces/ruby-app-custom-names/123.gemfile.lock b/test/acceptance/workspaces/ruby-app-custom-names/123.gemfile.lock new file mode 100644 index 00000000000..1471006e88e --- /dev/null +++ b/test/acceptance/workspaces/ruby-app-custom-names/123.gemfile.lock @@ -0,0 +1,26 @@ +GEM + remote: http://rubygems.org/ + specs: + crass (1.0.4) + lynx (0.4.0) + mini_portile2 (2.3.0) + nokogiri (1.8.5) + mini_portile2 (~> 2.3.0) + nokogumbo (1.5.0) + nokogiri + sanitize (4.6.2) + crass (~> 1.0.2) + nokogiri (>= 1.4.4) + nokogumbo (~> 1.4) + yard (0.8.0) + +PLATFORMS + ruby + +DEPENDENCIES + lynx (= 0.4.0) + sanitize (= 4.6.2) + yard (= 0.8.0) + +BUNDLED WITH + 1.16.5 diff --git a/test/acceptance/workspaces/ruby-app-custom-names/gemfiles/Gemfile.rails-2.4.5 b/test/acceptance/workspaces/ruby-app-custom-names/gemfiles/Gemfile.rails-2.4.5 new file mode 100644 index 00000000000..88d27cc9f0c --- /dev/null +++ b/test/acceptance/workspaces/ruby-app-custom-names/gemfiles/Gemfile.rails-2.4.5 @@ -0,0 +1,5 @@ +source :rubygems + +gem "sanitize", "4.6.2" +gem "yard", "0.8.0" +gem "lynx", "0.4.0" diff --git a/test/acceptance/workspaces/ruby-app-custom-names/gemfiles/Gemfile.rails-2.4.5.lock b/test/acceptance/workspaces/ruby-app-custom-names/gemfiles/Gemfile.rails-2.4.5.lock new file mode 100644 index 00000000000..1471006e88e --- /dev/null +++ b/test/acceptance/workspaces/ruby-app-custom-names/gemfiles/Gemfile.rails-2.4.5.lock @@ -0,0 +1,26 @@ +GEM + remote: http://rubygems.org/ + specs: + crass (1.0.4) + lynx (0.4.0) + mini_portile2 (2.3.0) + nokogiri (1.8.5) + mini_portile2 (~> 2.3.0) + nokogumbo (1.5.0) + nokogiri + sanitize (4.6.2) + crass (~> 1.0.2) + nokogiri (>= 1.4.4) + nokogumbo (~> 1.4) + yard (0.8.0) + +PLATFORMS + ruby + +DEPENDENCIES + lynx (= 0.4.0) + sanitize (= 4.6.2) + yard (= 0.8.0) + +BUNDLED WITH + 1.16.5