转载

为 Bluemix 上运行的 Node.js 应用程序自动收集法律报告

发布新的软件版本之前,开发人员和发布经理需要确保软件中包含的所有库(依赖项)已被授权用于商业用途。构建 Node.js 应用程序时,您可能使用数十个外部库,每个库都有不同的许可条款。收集所有这些库的信息可能很痛苦而且很耗时。本文介绍如何自动完成这些任务,并生成项目中所用全部依赖项的列表:列表中包含依赖项所遵守的许可,以及可在哪个网站或存储库中找到它们。

您需要满足的条件

  • 一个 Node.js 应用程序
  • 最新版本的 Node 包管理器 (npm)(Node.js 已安装 npm,但 npm 的更新频率比 Node.js 高,所以请确保您拥有最新的版本。)
  • IBM® Bluemix™ DevOps Services 管道
  • Grunt,JavaScript 任务运行程序(0.4.5 版或更高版本)

备注:本文选择 IBM Bluemix DevOps Services 作为例子,但是您可将同样的 Grunt 任务轻松集成到 Jenkins 作业中。您也可以修改我们所创建的代码,从而在 Gulp 中运行它,或者在 Grunt 以外的任何其他任务自动化框架中运行它。

相关主题: IBM Bluemix DevOps Services 简介 -- 利用交付管道自动部署到 Bluemix

第 1 步. 设置 Grunt

如果已设置好 Grunt,可跳到下一步。如果项目中还不包含 Grunt,可执行以下步骤设置它。您需要 Grunt 的命令行接口 (CLI) 和 Grunt Node 模块。

相关主题: 在项目中设置 Grunt

  1. 要安装 Grunt 的 CLI,可在项目的根文件夹运行以下命令。您可能需要使用 sudo (对于 OSX、Linux®、BSD 等)或以管理员身份(对于 Windows®)运行命令。

    要将 grunt 命令放到系统路径中,并允许从任何目录运行它:

    npm install -g grunt-cli
  2. 安装 Grunt CLI 不会将 Grunt 任务运行程序安装在您的项目中。要将它添加到项目中,可运行以下命令。这会将 Grunt 添加到 package.json 依赖项文件中并将其作为一个开发依赖项。
    npm install grunt --save-dev
  3. 创建一个 Gruntfile.js 文件。这应该是一个有效的 JavaScript 文件,与 package.json 文件一起位于项目的根目录中,而且应与项目源代码一同提交。

    下面一个 Gruntfile.js 文件示例:

    module.exports = function(grunt) {    grunt.initConfig({     pkg: grunt.file.readJSON('package.json')   });    grunt.registerTask('default');  };

第 2 步. 创建一个执行许可任务的脚本

为项目设置好 Grunt 后,创建一个新的 Grunt 任务文件来包含由 Grunt 执行的自定义代码。

  1. 在项目的根目录下创建一个名为 build_tasks 的文件夹,在此文件夹中创建一个名为 licenses.js 的文件。
  2. 将您的自定义 Grunt 任务放在这个文件中。就现在而言,可使用下面这个 licenses.js 文件。
    module.exports = function (grunt) {   'use strict';      grunt.registerTask('example', 'Example task', function () {      });  };
  3. 上面的代码注册一个可从 Gruntfile.js 调用的简单任务。为此,需要修改 Gruntfile.js,将这些任务加载到最近创建的 build_tasks 文件夹中。
    npm install grunt --save-dev module.exports = function(grunt) {    grunt.initConfig({     pkg: grunt.file.readJSON('package.json')   });    grunt.task.loadTasks('build_tasks');    grunt.registerTask('default', ['example']);  };
  4. 要测试它是否有效,可在命令行中从项目的根目录运行 grunt

    应该看到以下输出:

    Running "example" task  Done, without errors.

第 3 步. 收集服务器端依赖项(npm 模块)

相关主题: npm 是什么?

  1. grunt-license-finder Node 模块添加到项目中。从项目的根目录运行以下命令:
    npm install grunt-license-finder –-save-dev
  2. 安装该插件后,在您的 Gruntfile.js 文件中应使用以下 JavaScript 代码启用该插件:
    grunt.loadNpmTasks(‘grunt-license-finder');
  3. 在项目的 Gruntfile.js 文件中,将一个名为 license_finder 的节添加到已传入 grunt.initConfig()

    中的数据对象中:

    grunt.initConfig({     pkg: grunt.file.readJSON('package.json'),     license_finder: {            }   });

    新的 developerWorks Premium 会员计划提供了一张访问强大的开发工具和资源的全通票,包括 500 篇通过 Safari Books Online 提供的顶级技术文章(数十篇文章是专门针对 Web 开发人员的)、最重要开发人员活动的大幅折扣,最新的 O'Reilly 大会的视频回放,等等。立即注册。

    这个新节是指定各种选项的地方,这些选项用于生成报告。您可为服务器端依赖项创建两个不同的报告:一个用于生产依赖项,一个用于开发依赖项。

    生产依赖项由应用程序在服务器运行时部署和使用。开发依赖项是仅在开发和自动化期间使用的库,比如刚刚添加到项目的 gruntgrunt-license-finder

    将一个依赖项添加到 package.json 文件中时,可将它添加到开发依赖项或生产依赖项中。

  4. license_finder 任务添加两个目标,每种类型的依赖项一个目标,以便它生成两个单独的文件并更容易识别生产和开发依赖项。为此,在 license_finder 节中添加两个目标。
    grunt.initConfig({         pkg: grunt.file.readJSON('package.json'),         license_finder: {             dev: {                 options: {                     production: false,                     out: 'npm-dev-licenses.csv',                     csv: true                 }             },             prod: {                 options: {                     production: true,                     out: 'npm-prod-licenses.csv',                     csv: true                 }             }         }     });

    您可更改这些选项,使其与您想要的配置匹配。 production 选项指定它生成生产还是开发依赖项。 out 选项定义该报告的输出文件, csv 选项指定为报告生成一个 csv 文件。

  5. 您还需要创建一个目标任务,从而通过 license_finder 调用这两个任务:一个用于生产报告,一个用于开发报告。将以下代码行添加到 Gruntifle.js 文件中:
    grunt.registerTask('server-side-license', ['license_finder:dev', 'license_finder:prod']);
  6. 更改服务器端依赖项后,完成 Gruntfile.js 文件。
    module.exports = function (grunt) {      grunt.initConfig({         pkg: grunt.file.readJSON('package.json'),         license_finder: {             dev: {                 options: {                     production: false,                     out: 'npm-dev-licenses.csv',                     csv: true                 }             },             prod: {                 options: {                     production: true,                     out: 'npm-prod-licenses.csv',                     csv: true                 }             }         }     });      grunt.task.loadTasks('build_tasks');     grunt.loadNpmTasks('grunt-license-finder');      grunt.registerTask('server-side-license', ['license_finder:dev', 'license_finder:prod']);  };
  7. 现在您可从 Grunt 命令行运行 server-side-license

    任务。

    grunt server-side-license

    输出应该如下所示:

    Running "license_finder:dev" (license_finder) task Retrieved license information License information written to: npm-dev-licenses.csv Running "license_finder:prod" (license_finder) task Retrieved license information License information written to: npm-prod-licenses.csv  Done, without errors.

第 4 步. 收集客户端依赖项(Bower 组件)

Bower 是一个工具,使用它可以轻松地管理客户端依赖项。无需访问您想要使用的每个项目的站点并下载必要的库文件,您可创建一个 Bower 配置文件,自动完成此流程。

如果环境中没有 Bower,可按照这篇 教程 中的步骤设置它。

为您的项目安装并配置 Bower 后,所有客户端依赖项都存储在一个名为 bower.json 的文件中。确保项目中使用的所有客户端依赖项都是通过 Bower 添加的,而不是直接添加到页面中,这样所生成的报告才是准确无误的。

  1. 要收集 Bower 依赖项,可将 bower-license Node 模块添加到项目中。从项目的根目录中运行以下命令:
    npm install bower-license --save-dev
  2. 安装该插件后,在您的 license.js 文件中应使用以下 JavaScript 代码启用该插件:
    var license = require('bower-license');
  3. 加载此模块后,开始编码将使用 bower-license 的自定义任务。创建一个名为 run_bower_license 的任务来收集所有依赖项并将结果输出到一个文件中。将以下代码添加到 licenses.js 文件中。

    点击查看代码清单

    关闭 [x]

    var license = require('bower-license'), fs = require('fs');  module.exports = function (grunt) {      'use strict';      grunt.registerMultiTask('run_bower_license', 'Gather bower license report', function () {         var options = this.options({                 directory: 'bower_components',                 output: 'bower-license.csv'             }),             entry, item, prop, done, dependency;          done = this.async();          console.log('Executing run_bower_license task');          // If output file already exists, will delete it         if(grunt.file.exists(options.output)) {             console.log('Output file already exists. Will delete it');             grunt.file.delete(options.output);         }          license.init(options, function (data) {             for (entry in data) {                 item = {                     licenses: "",                     repository: "",                     homepage: ""                 };                  for (prop in data[entry]) {                     if (prop === 'licenses') {                         item.licenses = data[entry][prop];                     } else if (prop === 'repository') {                         item.repository = data[entry][prop];                         if (item.repository.constructor === Object) {                             item.repository = item.repository.url;                         }                     } else if (prop === 'homepage') {                         item.homepage = data[entry][prop];                     }                 }                  item.version = entry.substring(entry.indexOf('@') + 1, entry.length);                 item.name = entry.substring(0, entry.indexOf('@'));                  dependency = item.name + ',' + item.version + ',' + item.repository + ',' + item.licenses;                  if(item.homepage) {                     dependency += ',' + item.homepage;                 }                  fs.appendFileSync(options.output, dependency + '/r/n');             }              console.log('End of run_bower_license task');             done();          });      });  };

    此代码注册一个名为 run_bower_license 的 Grunt 任务,该任务接受两个参数—一个表示 Bower 组件存储在何处的目录,一个表示所生成的输出文件的名称。它删除输出文件(如果已存在)并调用 bower-license 库,该库从 Bower 读取所有客户端依赖项。

    对于返回的每个依赖项, run_bower_license 尝试获得库的名称、版本、git 存储库 URL、许可和主页。对于一个给定的库,可能并非所有这些信息都有,但所拥有的信息都会放在输出文件中。

  4. 在 Gruntfile.js 文件中,注册一个调用 run_bower_license 任务的新目标任务。将它命名为 client-side-license
    grunt.registerTask('client-side-license', ['run_bower_license:all']);
  5. 从 Grunt 命令行运行 client-side-license

    任务。

    grunt client-side-license

    输出应该如下所示:

    Running "run_bower_license:all" (run_bower_license) task Executing run_bower_license task Output file already exists. Will delete it End of run_bower_license task  Done, without errors.
  6. 创建一个名为 get-licenses 的任务,该任务同时调用客户端和服务器端版本。
    grunt.registerTask('client-side-license', ['run_bower_license:all']);
  7. 执行所有这些更改后,您的 Gruntfile.js 文件应该类似于:
    module.exports = function (grunt) {      grunt.initConfig({         pkg: grunt.file.readJSON('package.json'),         license_finder: {             dev: {                 options: {                     production: false,                     out: 'npm-dev-licenses.csv',                     csv: true                 }             },             prod: {                 options: {                     production: true,                     out: 'npm-prod-licenses.csv',                     csv: true                 }             }         },         run_bower_license: {             all: {               options: {                     directory: 'bower_components',                     output: 'bower-license.csv'               }             }         }     });      grunt.task.loadTasks('build_tasks');     grunt.loadNpmTasks('grunt-license-finder');      grunt.registerTask('server-side-license', ['license_finder:dev', 'license_finder:prod']);     grunt.registerTask('client-side-license', ['run_bower_license:all']);     grunt.registerTask('get-licenses', ['server-side-license', 'client-side-license']);  };
  8. 从 Grunt 命令行运行 get-licenses

    任务,获得客户端和服务器端报告。

    grunt get-licenses

    输出应该如下所示:

    Running "license_finder:dev" (license_finder) task Retrieved license information License information written to: npm-dev-licenses.csv  Running "license_finder:prod" (license_finder) task Retrieved license information License information written to: npm-prod-licenses.csv  Running "run_bower_license:all" (run_bower_license) task Executing run_bower_license task Output file already exists. Will delete it End of run_bower_license task  Done, without errors.

第 5 步. 在 Bluemix 管道上合并许可脚本

在本节中,您将学习如何自动执行 IBM Bluemix DevOps Services 上的许可任务。

进入项目的 Build & Deploy 视图后,您可看到该项目的管道。为您的项目启用此特性后,创建这个管道包含两个阶段:一个是执行构建工作,另一个将应用程序部署到 Bluemix。

为 Bluemix 上运行的 Node.js 应用程序自动收集法律报告

点击查看大图

关闭 [x]

为 Bluemix 上运行的 Node.js 应用程序自动收集法律报告

  1. 单击 ADD STAGE 创建一个新阶段。 为 Bluemix 上运行的 Node.js 应用程序自动收集法律报告
  2. 命名该阶段并配置其输入。在 Generate Licenses 面板上的 Input 选项卡下,按如下所示配置 Input Settings,然后单击 SAVE

    • Input Type :Build Artifacts
    • Stage :Build Stage
    • Job :Build
    • Stage Trigger :Run jobs when the previous stage is completed.

    这意味着在构建阶段完成后,会复制所有构建工件,以便执行许可任务。

    为 Bluemix 上运行的 Node.js 应用程序自动收集法律报告

    点击查看大图

    关闭 [x]

    为 Bluemix 上运行的 Node.js 应用程序自动收集法律报告

  3. 在 Jobs 选项卡下,单击 ADD JOB ,添加一个新作业。 为 Bluemix 上运行的 Node.js 应用程序自动收集法律报告

    点击查看大图

    关闭 [x]

    为 Bluemix 上运行的 Node.js 应用程序自动收集法律报告

  4. 在 SELECT JOB TYPE 下拉列表中,选择 Build为 Bluemix 上运行的 Node.js 应用程序自动收集法律报告

    点击查看大图

    关闭 [x]

    为 Bluemix 上运行的 Node.js 应用程序自动收集法律报告

  5. 在 Execute License tasks 面板上,选择 Grunt 作为 Builder Type,输入如下 Build Shell Command:
    #!/bin/bash npm install node_modules/bower/bin/bower install grunt get-licenses
    为 Bluemix 上运行的 Node.js 应用程序自动收集法律报告

    点击查看大图

    关闭 [x]

    为 Bluemix 上运行的 Node.js 应用程序自动收集法律报告

  6. 单击 SAVE ,保存您的阶段配置。如下图所示,您的管道现在应有 3 个阶段:Build Stage、Deploy Stage 和 Generate Licenses。 为 Bluemix 上运行的 Node.js 应用程序自动收集法律报告

    点击查看大图

    关闭 [x]

    为 Bluemix 上运行的 Node.js 应用程序自动收集法律报告

  7. 单击 Run Stage 箭头,再次运行管道的第一个阶段,如下所示。再次按顺序执行所有阶段。 为 Bluemix 上运行的 Node.js 应用程序自动收集法律报告
  8. 成功执行 Generate Licenses 阶段后,单击 Last Execution Results ,查看阶段执行的日志,以及已生成的工件。 为 Bluemix 上运行的 Node.js 应用程序自动收集法律报告 为 Bluemix 上运行的 Node.js 应用程序自动收集法律报告

    点击查看大图

    关闭 [x]

    为 Bluemix 上运行的 Node.js 应用程序自动收集法律报告

  9. 单击 ARTIFACTS 选项卡,查看此任务的所有文件,包括内含服务器端和客户端依赖项的报告( bower-license.csvnpm-dev-licenses.csvnpm-prod-licenses.csv )。 为 Bluemix 上运行的 Node.js 应用程序自动收集法律报告
  10. 单击想要下载的文件旁边的 Download为 Bluemix 上运行的 Node.js 应用程序自动收集法律报告
  11. 这是已生成报告示例。
    1. 对于 bower-license.csv (客户端依赖项):

      点击查看代码清单

      关闭 [x]

      angular-bootstrap,0.13.0,,MIT d3,undefined,,MIT* jquery,2.1.4,,MIT angular,1.4.1,git+https://github.com/angular/angular.js,MIT angular-animate,1.3.16,git+https://github.com/angular/angular.js,MIT angular-resource,1.3.16,git+https://github.com/angular/angular.js,MIT angular-route,1.3.16,git+https://github.com/angular/angular.js,MIT angular-sanitize,1.4.1,git+https://github.com/angular/angular.js,MIT bootstrap,3.1.1,git+https://github.com/twbs/bootstrap,MIT jquery-ui,1.11.4,https://github.com/jquery/jquery-ui,MIT angular-ui-bootstrap,0.13.0,git+https://github.com/angular-ui/bootstrap,MIT,https://github.com/angular-ui/bootstrap Flot,0.8.3,,UNKNOWN
    2. 对于 npm-prod-license.csv (服务器端依赖项):

      点击查看代码清单

      关闭 [x]

      name,version,directory,repository,summary,from package.json,from license,from readme NodejsStarterApp,0.0.1,/home/fmariani/bluemix/MyTestLicensesApp,(none),MIT,,MIT,MIT accepts,1.2.12,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/accepts,git+https://github.com/jshttp/accepts,MIT,MIT,MIT, argparse,1.0.2,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/cfenv/node_modules/js-yaml/node_modules/argparse,http://github.com/nodeca/argparse,MIT,MIT,MIT,MIT cfenv,1.0.0,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/cfenv,git+https://github.com/cloudfoundry-community/node-cfenv,Apache;Apache-2.0,Apache-2.0,Apache, content-disposition,0.5.0,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/content-disposition,git+https://github.com/jshttp/content-disposition,MIT,MIT,MIT, content-type,1.0.1,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/content-type,git+https://github.com/jshttp/content-type,MIT,MIT,MIT, cookie,0.1.2,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/cookie,http://github.com/shtylman/node-cookie,MIT,,MIT, cookie-signature,1.0.6,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/cookie-signature,git+https://github.com/visionmedia/node-cookie-signature,MIT,MIT,,MIT crc,3.2.1,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/etag/node_modules/crc,http://github.com/alexgorbatchev/node-crc,MIT,MIT,MIT,MIT debug,2.2.0,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/debug,http://github.com/visionmedia/debug,MIT,MIT,,MIT depd,1.0.1,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/depd,git+https://github.com/dougwilson/nodejs-depd,MIT,MIT,MIT, destroy,1.0.3,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/send/node_modules/destroy,git+https://github.com/stream-utils/destroy,MIT,MIT,, ee-first,1.1.0,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/on-finished/node_modules/ee-first,git+https://github.com/jonathanong/ee-first,MIT,MIT,MIT, escape-html,1.0.1,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/escape-html,git+https://github.com/component/escape-html,Unknown,,, esprima,2.0.0,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/cfenv/node_modules/js-yaml/node_modules/esprima,git+https://github.com/jquery/esprima,BSD,BSD,,BSD etag,1.6.0,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/etag,git+https://github.com/jshttp/etag,MIT,MIT,MIT, express,4.12.4,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express,git+https://github.com/strongloop/express,MIT,MIT,MIT, finalhandler,0.3.6,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/finalhandler,git+https://github.com/pillarjs/finalhandler,MIT,MIT,MIT, forwarded,0.1.0,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/proxy-addr/node_modules/forwarded,git+https://github.com/jshttp/forwarded,MIT,MIT,MIT, fresh,0.2.4,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/fresh,git+https://github.com/jshttp/fresh,MIT,MIT,MIT, ipaddr.js,1.0.1,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/proxy-addr/node_modules/ipaddr.js,http://github.com/whitequark/ipaddr.js,MIT,MIT,, js-yaml,3.2.7,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/cfenv/node_modules/js-yaml,http://github.com/nodeca/js-yaml,MIT,MIT,MIT, lodash,3.10.1,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/cfenv/node_modules/js-yaml/node_modules/argparse/node_modules/lodash,git+https://github.com/lodash/lodash,MIT,MIT,, media-typer,0.3.0,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/type-is/node_modules/media-typer,git+https://github.com/jshttp/media-typer,MIT,MIT,MIT, merge-descriptors,1.0.0,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/merge-descriptors,git+https://github.com/component/merge-descriptors,MIT,MIT,MIT, methods,1.1.1,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/methods,git+https://github.com/jshttp/methods,MIT,MIT,MIT, mime,1.3.4,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/send/node_modules/mime,git+https://github.com/broofa/node-mime,MIT,MIT,, mime-db,1.17.0,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/accepts/node_modules/mime-types/node_modules/mime-db,git+https://github.com/jshttp/mime-db,MIT,MIT,MIT, mime-types,2.1.5,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/accepts/node_modules/mime-types,git+https://github.com/jshttp/mime-types,MIT,MIT,MIT, ms,0.7.1,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/debug/node_modules/ms,http://github.com/guille/ms.js,MIT,,MIT,MIT negotiator,0.5.3,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/accepts/node_modules/negotiator,git+https://github.com/jshttp/negotiator,MIT,MIT,MIT, on-finished,2.2.1,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/on-finished,git+https://github.com/jshttp/on-finished,MIT,MIT,MIT, parseurl,1.3.0,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/parseurl,git+https://github.com/expressjs/parseurl,MIT,MIT,MIT, path-to-regexp,0.1.3,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/path-to-regexp,git+https://github.com/component/path-to-regexp,Unknown,,, ports,1.1.0,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/cfenv/node_modules/ports,git+https://github.com/hoodiehq/node-ports,Apache 2.0,Apache 2.0,, proxy-addr,1.0.8,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/proxy-addr,git+https://github.com/jshttp/proxy-addr,MIT,MIT,MIT, qs,2.4.2,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/qs,git+https://github.com/hapijs/qs,BSD,BSD,, range-parser,1.0.2,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/range-parser,git+https://github.com/jshttp/range-parser,MIT,MIT,MIT, send,0.12.3,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/send,git+https://github.com/pillarjs/send,MIT,MIT,MIT, serve-static,1.9.3,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/serve-static,git+https://github.com/expressjs/serve-static,MIT,MIT,MIT, sprintf-js,1.0.3,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/cfenv/node_modules/js-yaml/node_modules/argparse/node_modules/sprintf-js,git+https://github.com/alexei/sprintf.js,BSD;BSD-3-Clause,BSD-3-Clause,,BSD type-is,1.6.7,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/type-is,git+https://github.com/jshttp/type-is,MIT,MIT,MIT, underscore,1.7.0,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/cfenv/node_modules/underscore,http://github.com/jashkenas/underscore,MIT,MIT,, utils-merge,1.0.0,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/utils-merge,http://github.com/jaredhanson/utils-merge,MIT,MIT,MIT,MIT vary,1.0.1,/home/fmariani/bluemix/MyTestLicensesApp/node_modules/express/node_modules/vary,git+https://github.com/jshttp/vary,MIT,MIT,MIT   name,version,directory,repository,summary,from package.json,from license,from readme

结束语

本文介绍了如何在发布新软件之前自动获取项目中所有依赖项的必要信息。在示例中,自动化工作是在 IBM Bluemix DevOps Services 上的项目管道中完成的,所以每次将一个包含代码更改的新提交推送到服务器时,都会再次执行整个管道并更新所有许可报告。我希望这个自动化流程可让您在收集应用程序法律信息的枯燥任务中节省一些时间,少些烦恼!

正文到此结束
Loading...