自定义适用于 Azure Pipelines 的 JavaScript
可以使用 Azure Pipelines 生成 JavaScript 应用,而无需设置自己的任何基础结构。 通常用于生成、测试和运行 JavaScript 应用(如 npm、Node、Yarn 和 Gulp)的工具在 Azure Pipelines 中的 Microsoft 托管代理 上预安装。
有关预安装的 Node.js 和 npm 版本,请参阅 Microsoft 托管的代理。 若要在 Microsoft 托管的代理上安装特定版本的这些工具,请将 Node Tool Installer 任务添加到进程的开头。 还可以使用 自承载 代理。
若要使用 JavaScript 创建第一个管道,请参阅 JavaScript 快速入门。
使用特定版本的 Node.js
如果需要尚未安装在 Microsoft 托管代理上的 Node.js 和 npm 版本,请使用 Node 工具安装程序任务。 将以下代码片段添加到 azure-pipelines.yml
文件。
注意
托管代理会定期更新,并且设置此任务会导致每次运行管道时花费大量时间更新到较新的次要版本。 仅在管道中需要特定 Node 版本时才使用此任务。
- task: NodeTool@0
inputs:
versionSpec: '16.x' # replace this value with the version that you need for your project
如果需要已在代理上安装的 Node.js/npm 版本:
在管道中,选择 “任务”,选择运行生成任务的阶段,然后选择 + 向该阶段添加新任务。
在任务目录中,查找并添加 节点工具安装程序 任务。
选择该任务并指定要安装的Node.js运行时的版本。
若要仅更新 npm 工具,请在 npm i -g npm@version-number
生成过程中运行该命令。
使用多个节点版本
可以使用 Node 工具安装程序任务在多个版本的 Node 上生成和测试应用。
pool:
vmImage: 'ubuntu-latest'
strategy:
matrix:
node_16_x:
node_version: 16.x
node_13_x:
node_version: 18.x
steps:
- task: NodeTool@0
inputs:
versionSpec: $(node_version)
- script: npm install
请参阅 多配置执行。
在生成代理上安装工具
如果项目或package-lock.json
文件中有开发依赖项package.json
的工具,请通过 npm 安装工具和依赖项。 工具的确切版本在项目中定义,与生成代理上存在的其他版本隔离。
使用脚本通过 package.json 进行安装
- script: npm install --only=dev
使用 npm 任务通过 package.json 进行安装
- task: Npm@1
inputs:
command: 'install'
使用 npm npx
包运行程序以这种方式安装工具,检测在路径解析中以这种方式安装的工具。 以下示例调用 mocha
测试运行程序,但在通过 npm install -g
) 版本使用全局安装 (之前,查找安装为开发依赖项的版本。
- script: npx mocha
若要安装项目需要但未设置为开发依赖项 package.json
的工具,请从管道中的脚本阶段调用 npm install -g
。
The following example installs the latest version of the Angular CLI by using npm
. 然后 ng
,管道的其余部分可以使用其他阶段的工具 script
。
注意
在 Microsoft 托管的 Linux 代理上,使用 sudo
命令开头,如下所示 sudo npm install -g
。
- script: npm install -g @angular/cli
提示
这些任务每次运行管道时都会运行,因此请注意安装工具对生成时间的影响。 如果开销对生成性能产生严重影响,请考虑使用所需的工具版本配置 自承载代理 。
管理依赖项
在生成中,使用 Yarn 或 Azure Artifacts 从公共 npm 注册表下载包。 此注册表是在 .npmrc 文件中指定的专用 npm 注册表类型。
使用 npm
可以通过以下方式使用 npm 下载生成包:
- 直接在管道中运行
npm install
,因为它是在不进行身份验证的情况下从注册表下载包的最简单方法。 如果生成不需要运行代理上的开发依赖项,则可以使用选项npm install
加快生成时间--only=prod
。 - 使用 npm 任务。 使用经过身份验证的注册表时,此任务非常有用。
- 使用 npm 身份验证任务。 当你从任务运行程序内部运行
npm install
-Gulp、Grunt 或 Maven 时,此任务非常有用。
如果要指定 npm 注册表,请将 URL .npmrc
放入存储库中的文件中。
如果源经过身份验证,请在 Project 设置中的“服务”选项卡上创建 npm 服务连接以管理其凭据。
若要在管道中使用脚本安装 npm 包,请将以下代码片段添加到 azure-pipelines.yml
其中。
- script: npm install
若要使用文件中指定的 .npmrc
专用注册表,请将以下代码片段添加到 azure-pipelines.yml
。
- task: Npm@1
inputs:
customEndpoint: <Name of npm service connection>
若要通过任务运行程序(如 Gulp)将注册表凭据传递给 npm 命令,请在调用任务运行程序之前将 azure-pipelines.yml
以下任务添加到其中。
- task: npmAuthenticate@0
inputs:
customEndpoint: <Name of npm service connection>
如果由于从 npm 注册表还原包时偶尔出现连接问题而生成失败,则可以将 Azure Artifacts 与 上游源一起使用,并缓存包。 连接到 Azure Artifacts 时,管道的凭据会自动使用。 这些凭据通常派生自 Project Collection 生成服务 帐户。
如果使用 Microsoft 托管的代理,则每次运行生成时都会获得一台新计算机,这意味着每次还原依赖项,这可能需要大量时间。 若要缓解此问题,可以使用 Azure Artifacts 或自承载代理 - 然后获得使用包缓存的好处。
使用 Yarn
使用脚本阶段调用 Yarn 来还原依赖项。 Yarn 在一些 Microsoft 托管的代理上预安装。 可以像任何其他工具一样在自承载代理上安装和配置它。
- script: yarn install
运行 JavaScript 编译器
使用 Babel 和 TypeScripttsc
编译器等编译器将源代码转换为Node.js运行时或 Web 浏览器中可使用的版本。
如果在运行编译器的项目package.json
文件中设置了脚本对象,请使用脚本任务在管道中调用它。
- script: npm run compile
可以使用脚本任务直接从管道调用编译器。 这些命令从克隆的源代码存储库的根目录运行。
- script: tsc --target ES6 --strict true --project tsconfigs/production.json
运行单元测试
将管道配置为运行 JavaScript 测试,以便生成采用 JUnit XML 格式格式化的结果。 然后,可以使用内置的 发布测试结果 任务发布结果。
如果测试框架不支持 JUnit 输出,请通过合作伙伴报告模块(如 mocha-junit-reporter)添加支持。 可以更新测试脚本以使用 JUnit 记者,或者如果记者支持命令行选项,请将这些选项传递到任务定义中。
下表列出了最常用的测试运行程序和可用于生成 XML 结果的记者:
测试运行程序 | 记者生成 XML 报告 |
---|---|
摩 卡 | mocha-junit-reporter 赛普拉斯-多记者 |
茉莉花 | jasmine-记者 |
开玩笑 | jest-junit jest-junit-reporter |
业 | 卡玛-朱尼特-记者 |
Ava | tap-xunit |
以下示例使用 mocha-junit-reporter ,并使用脚本直接调用 mocha test
。 此脚本在默认位置 ./test-results.xml
生成 JUnit XML 输出。
- script: mocha test --reporter mocha-junit-reporter
如果在项目 package.json 文件中定义了 test
脚本,则可以使用 npm test
a0/> 调用它。
- script: npm test
发布测试结果
若要发布结果,请使用 “发布测试结果 ”任务。
- task: PublishTestResults@2
condition: succeededOrFailed()
inputs:
testRunner: JUnit
testResultsFiles: '**/test-results.xml'
发布代码覆盖率结果
如果测试脚本运行代码覆盖率工具(如 伊斯坦布尔),请添加 “发布代码覆盖率结果 ”任务。 执行此操作时,可以在生成摘要中找到覆盖率指标,并下载 HTML 报表以供进一步分析。 该任务需要 Cobertura 或 JaCoCo 报告输出,因此请确保代码覆盖率工具使用必要的选项运行以生成正确的输出。 例如,--report cobertura
。
以下示例使用 nyc、伊斯坦布尔命令行接口以及 mocha-junit-reporter 并调用 npm test
命令。
- script: |
nyc --reporter=cobertura --reporter=html \
npm test -- --reporter mocha-junit-reporter --reporter-options mochaFile=./test-results.xml
displayName: 'Build code coverage report'
- task: PublishCodeCoverageResults@1
inputs:
codeCoverageTool: Cobertura # or JaCoCo
summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/*coverage.xml'
reportDirectory: '$(System.DefaultWorkingDirectory)/**/coverage'
使用管道中的 “发布测试结果 ”和 “发布代码覆盖率结果 ”任务,使用伊斯坦布尔发布测试结果和代码覆盖率结果。
设置发布测试结果任务的控件选项以运行该任务,即使上一个任务失败,除非部署被取消。
测试浏览器端到端
使用 Protractor 或 Karma 等工具在无头浏览器中运行测试。 然后,使用以下步骤将生成的结果发布到 Azure DevOps:
- 在生成代理上安装无外设浏览器测试驱动程序(如无头 Chrome 或 Firefox)或浏览器模拟工具(如 PhantomJS)。
- 根据工具的文档,将测试框架配置为使用所选的无外设浏览器/驱动程序选项。
- 配置测试框架 (通常使用记者插件或配置) 输出 JUnit 格式的测试结果。
- 设置脚本任务以运行启动无外设浏览器实例所需的任何 CLI 命令。
- 在管道阶段以及单元测试中运行端到端测试。
- 使用与单元测试相同的 发布测试结果 任务发布结果。
打包 Web 应用
打包应用程序,将所有应用程序模块与中间输出和依赖项捆绑到可供部署的静态资产中。 在编译和测试之后添加管道阶段,以使用 Angular CLI 运行 webpack 或 ng 生成等工具。
第一个示例调用 webpack
。 若要执行此操作,请确保将其 webpack
配置为 package.json 项目文件中的开发依赖项。 此操作使用默认配置运行 webpack
,除非项目根文件夹中有一个 webpack.config.js
文件。
- script: webpack
下一个示例使用 npm 任务调用npm run build
build
在项目 package.json 中定义的脚本对象。 在项目中使用脚本对象会将生成逻辑移入源代码和管道外。
- script: npm run build
实现 JavaScript 框架
Angular
对于Angular应用,可以包含特定于 Angular 的命令,例如 ng 测试、ng 生成和 ng e2e。 若要在管道中使用 Angular CLI 命令,请在生成代理上安装 angular/cli npm 包。
注意
在 Microsoft 托管的 Linux 代理上,使用命令开头 sudo
,例如 sudo npm install -g
。
- script: |
npm install -g @angular/cli
npm install
ng build --prod
将以下任务添加到管道:
npm
- 命令:
custom
- 命令和参数:
install -g @angular/cli
- 命令:
npm
- 命令:
install
- 命令:
bash
- 类型:
inline
- 脚本:
ng build --prod
- 类型:
对于管道中需要浏览器运行的测试(例如,在运行 Karma 的初学者应用中的 ng 测试 命令),请使用无头浏览器而不是标准浏览器。 在Angular初学者应用中:
将
browsers
karma.conf.js 项目文件中的条目从browsers: ['Chrome']
更改为browsers: ['ChromeHeadless']
。将
singleRun
karma.conf.js 项目文件中的条目从值false
更改为true
。 此更改有助于确保 Karma 进程在运行后停止。
React和 Vue
React和 Vue 应用的所有依赖项均在 package.json 文件中捕获。 azure-pipelines.yml 文件包含标准Node.js脚本:
- script: |
npm install
displayName: 'npm install'
- script: |
npm run build
displayName: 'npm build'
生成文件位于新文件夹中, dist
(Vue) 或build
(React) 。 此代码片段将生成一个已准备好发布的项目 www
。 它使用 节点安装程序、 复制文件以及 发布生成项目 任务。
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
steps:
- task: NodeTool@0
inputs:
versionSpec: '16.x'
displayName: 'Install Node.js'
- script: |
npm install
displayName: 'npm install'
- script: |
npm run build
displayName: 'npm build'
- task: CopyFiles@2
inputs:
Contents: 'build/**' # Pull the build directory (React)
TargetFolder: '$(Build.ArtifactStagingDirectory)'
- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: $(Build.ArtifactStagingDirectory) # dist or build files
ArtifactName: 'www' # output artifact named www
若要发布,请将发布任务指向 dist
或 build
项目,并使用 Azure Web 应用部署任务。
Webpack
可以使用 Webpack 配置文件指定编译器(如 Babel 或 TypeScript)以将 JSX 或 TypeScript 转译为普通 JavaScript,以及捆绑应用。
- script: |
npm install webpack webpack-cli --save-dev
npx webpack --config webpack.config.js
将以下任务添加到管道:
npm
- 命令:
custom
- 命令和参数:
install -g webpack webpack-cli --save-dev
- 命令:
bash
- 类型:
inline
- 脚本:
npx webpack --config webpack.config.js
- 类型:
生成任务运行程序
通常使用 Gulp 或 Grunt 作为任务运行程序来生成和测试 JavaScript 应用。
Gulp
Gulp 预安装在 Microsoft 托管的代理上。 gulp
在 YAML 文件中运行以下命令:
- script: gulp # include any additional options that are needed
如果gulpfile.js文件中的步骤需要使用 npm 注册表进行身份验证:
- task: npmAuthenticate@0
inputs:
customEndpoint: <Name of npm service connection>
- script: gulp # include any additional options that are needed
添加 发布测试结果 任务,将 JUnit 或 xUnit 测试结果发布到服务器。
- task: PublishTestResults@2
inputs:
testResultsFiles: '**/TEST-RESULTS.xml'
testRunTitle: 'Test results for JavaScript using gulp'
添加 “发布代码覆盖率结果 ”任务,将代码覆盖率结果发布到服务器。 可以在生成摘要中找到覆盖率指标,并且可以下载 HTML 报表进行进一步分析。
- task: PublishCodeCoverageResults@1
inputs:
codeCoverageTool: Cobertura
summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/*coverage.xml'
reportDirectory: '$(System.DefaultWorkingDirectory)/**/coverage'
如果应用使用 Gulp 创建管道,最简单的方法是在创建管道时将 Node.js与 gulp 生成模板配合使用。 此模板会自动添加各种任务以调用 Gulp 命令并发布项目。 在任务中,选择“ 启用代码覆盖率” 以使用伊斯坦布尔启用代码覆盖率。
Grunt
Grunt 在 Microsoft 托管的代理上预安装。 若要在 YAML 文件中运行 grunt 命令,请执行以下操作:
- script: grunt # include any additional options that are needed
如果文件中的步骤 Gruntfile.js
需要使用 npm 注册表进行身份验证:
- task: npmAuthenticate@0
inputs:
customEndpoint: <Name of npm service connection>
- script: grunt # include any additional options that are needed
如果应用使用 Grunt 创建管道,最简单的方法是在创建管道时将 Node.js与 Grunt 生成模板配合使用。 这会自动添加各种任务来调用 Gulp 命令和发布项目。 在任务中,选择“ 发布到 TFS/Team Services ”选项以发布测试结果,然后选择“ 启用代码覆盖率” 以使用伊斯坦布尔启用代码覆盖率。
打包并交付代码
生成并测试应用后,可以将生成输出上传到 Azure Pipelines、创建和发布 npm 或 Maven 包,或将生成输出打包到.zip文件中,以便部署到 Web 应用程序。
将文件发布到 Azure Pipelines
若要上传整个工作目录的文件,请使用 “发布生成项目 ”任务,并将以下内容添加到文件中 azure-pipelines.yml
。
- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: '$(System.DefaultWorkingDirectory)'
若要上传文件的子集,请先使用 “复制文件 ”任务将所需文件从工作目录复制到过渡目录,然后使用 “发布生成项目”任务。
- task: CopyFiles@2
inputs:
SourceFolder: '$(System.DefaultWorkingDirectory)'
Contents: |
**\*.js
package.json
TargetFolder: '$(Build.ArtifactStagingDirectory)'
- task: PublishBuildArtifacts@1
将模块发布到 npm 注册表
如果项目的输出是 npm
供其他项目使用的模块,而不是 Web 应用程序,请使用 npm 任务将模块发布到本地注册表或公共 npm 注册表。 每次发布时提供唯一的名称/版本组合。
示例
第一个示例假设你通过对版本控制中的文件所做的更改package.json
来管理版本信息 (,例如通过 npm 版本) 。 以下示例使用脚本任务发布到公共注册表。
- script: npm publish
下一个示例将发布到存储库 .npmrc
文件中定义的自定义注册表。 设置 npm 服务连接 ,以在生成运行时将身份验证凭据注入连接。
- task: Npm@1
inputs:
command: publish
publishRegistry: useExternalRegistry
publishEndpoint: https://my.npmregistry.com
最后一个示例将模块发布到Azure DevOps Services包管理源。
- task: Npm@1
inputs:
command: publish
publishRegistry: useFeed
publishFeed: https://my.npmregistry.com
有关版本控制和发布 npm 包的详细信息,请参阅发布 npm 包,以及如何在生成过程中对 npm 包进行版本控制?
部署 Web 应用
若要创建可供发布到 Web 应用的.zip文件存档,请使用 存档文件 任务:
- task: ArchiveFiles@2
inputs:
rootFolderOrFile: '$(System.DefaultWorkingDirectory)'
includeRootFolder: false
若要将此存档发布到 Web 应用,请参阅 Azure Web 应用部署。
将项目发布到 Azure Pipelines
使用 “发布生成项目”任务 将文件从生成发布到 Azure Pipelines。
发布到 npm 注册表
若要创建和发布 npm 包,请使用 npm 任务。 有关版本控制和发布 npm 包的详细信息,请参阅 发布 npm 包。
部署 Web 应用
若要创建可供发布到 Web 应用的.zip文件存档,请使用 存档文件任务。 若要将此存档发布到 Web 应用,请参阅 Azure Web 应用部署。
疑难解答
如果可以在开发计算机上生成项目,但在 Azure Pipelines 上生成项目时遇到问题,请浏览以下潜在原因和纠正措施:
检查开发计算机上的 Node.js 版本和任务运行程序是否与代理上的版本匹配。 可以在管道中包含命令行脚本,以
node --version
检查代理上安装的内容。 如本指南中所述,请使用 Node Tool Installer (,) 在代理上部署同一版本,或运行npm install
命令将工具更新为所需版本。如果在还原包时生成间歇性失败,npm 注册表出现问题,或者 Azure 数据中心和注册表之间存在网络问题。 我们无法控制这些因素。 了解如何将 Azure Artifacts 与 npm 注册表配合使用作为上游源来提高生成的可靠性。
如果使用
nvm
管理不同版本的Node.js,请考虑改为切换到 Node Tool Installer 任务。nvm
(由于 macOS image.)nvm
通过添加 shell 别名和更改PATH
来管理多个Node.js版本,这与 Azure Pipelines 在新进程中运行每个任务的方式交互不佳。Node Tool Installer 任务可正确处理此模型。 但是,如果你的工作需要使用
nvm
,则可以将以下脚本添加到每个管道的开头:steps: - bash: | NODE_VERSION=16 # or whatever your preferred version is npm config delete prefix # avoid a warning . ${NVM_DIR}/nvm.sh nvm use ${NODE_VERSION} nvm alias default ${NODE_VERSION} VERSION_PATH="$(nvm_version_path ${NODE_VERSION})" echo "##vso[task.prependPath]$VERSION_PATH"
然后,
node
其他命令行工具适用于管道作业的其余部分。 在使用该nvm
命令的每个步骤中,使用以下代码启动脚本:- bash: | . ${NVM_DIR}/nvm.sh nvm <command>
常见问题解答
问:在哪里可以了解有关 Azure Artifacts 和包管理服务的详细信息?
问:我可以在哪里了解有关任务的详细信息?
答: 生成、发布和测试任务
问:如何实现修复管道故障,并显示消息“严重错误:CALL_AND_RETRY_LAST分配失败 - JavaScript 堆内存不足”?
答:当Node.js包超出内存使用量限制时,会发生此故障类型。 若要解决此问题,请添加一个变量,例如 NODE_OPTIONS
,并为其赋值 --max_old_space_size=16384。
问:如何在生成过程中对 npm 包进行版本控制?
答:一个选项是结合使用版本控件和 npm 版本。 在管道运行结束时,可以使用新版本更新存储库。 在此 YAML 中,有一个 GitHub 存储库,包将部署到 npmjs。 如果 npmjs 上的包版本与 package.json
文件不匹配,则生成将失败。
variables:
MAP_NPMTOKEN: $(NPMTOKEN) # Mapping secret var
trigger:
- none
pool:
vmImage: 'ubuntu-latest'
steps: # Checking out connected repo
- checkout: self
persistCredentials: true
clean: true
- task: npmAuthenticate@0
inputs:
workingFile: .npmrc
customEndpoint: 'my-npm-connection'
- task: NodeTool@0
inputs:
versionSpec: '16.x'
displayName: 'Install Node.js'
- script: |
npm install
displayName: 'npm install'
- script: |
npm pack
displayName: 'Package for release'
- bash: | # Grab the package version
v=`node -p "const p = require('./package.json'); p.version;"`
echo "##vso[task.setvariable variable=packageVersion]$v"
- task: CopyFiles@2
inputs:
contents: '*.tgz'
targetFolder: $(Build.ArtifactStagingDirectory)/npm
displayName: 'Copy archives to artifacts staging directory'
- task: CopyFiles@2
inputs:
sourceFolder: '$(Build.SourcesDirectory)'
contents: 'package.json'
targetFolder: $(Build.ArtifactStagingDirectory)/npm
displayName: 'Copy package.json'
- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)/npm'
artifactName: npm
displayName: 'Publish npm artifact'
- script: | # Config can be set in .npmrc
npm config set //registry.npmjs.org/:_authToken=$(MAP_NPMTOKEN)
npm config set scope "@myscope"
# npm config list
# npm --version
npm version patch --force
npm publish --access public
- task: CmdLine@2 # Push changes to GitHub (substitute your repo)
inputs:
script: |
git config --global user.email "username@contoso.com"
git config --global user.name "Azure Pipeline"
git add package.json
git commit -a -m "Test Commit from Azure DevOps"
git push -u origin HEAD:main