使用 Azure Pipelines 实现持续集成和持续部署

Azure Pipelines 是更高版本的 Azure DevOps 内部版本和发布版本功能。

本文介绍了如何为 Azure Pipelines 环境设置持续集成和持续部署,以便能够自动执行 SharePoint 框架生成、单元测试和部署。

在 Azure 多级管道与 Azure DevOps 内部版本和发布版本之间进行选择

目前有两种方法可用于实现持续集成和 Azure DevOps 部署。 Azure 内部版本和发布版本为历史版本,提供了图形版体验,并将定义存储在向用户隐匿的 JSON 文档中。

Azure 多级管道依赖于在存储库中存储为 YAML 文件的管道定义,提供透明度、版本历史记录和可重复性。 针对 SharePoint 框架对这两种方法进行了描述:

实现持续集成和持续测试

以下 YAML 模板介绍了持续集成和持续测试阶段。 将下面的内容复制到名为 azure-pipelines-build-template.yml 的项目的根目录处的一个新文件中。

parameters:
  name: ''
jobs:
  - job: ${{ parameters.name }}
    pool:
      vmImage: 'ubuntu-latest'
      demands:
      - npm
      - node.js
      - java
    variables:
      npm_config_cache: $(Pipeline.Workspace)/.npm

    steps:
      - checkout: self

      - task: NodeTool@0
        displayName: 'Use Node 10.x'
        inputs:
          versionSpec: 10.x
          checkLatest: true

      - task: CacheBeta@1
        inputs:
          key: npm | $(Agent.OS) | package-lock.json
          path: $(npm_config_cache)
          cacheHitVar: CACHE_RESTORED
      - script: npm ci
        displayName: 'npm ci'

      - task: Gulp@0
        displayName: 'Bundle project'
        inputs:
          targets: bundle
          arguments: '--ship'

      - script: npm test
        displayName: 'npm test'

      - task: PublishTestResults@2
        displayName: Publish test results
        inputs:
          testResultsFormat: JUnit
          testResultsFiles: '**/junit.xml'
          #failTaskOnFailedTests: true #if we want to fail the build on failed unit tests

      - task: PublishCodeCoverageResults@1
        displayName: 'Publish code coverage results'
        inputs:
          codeCoverageTool: Cobertura
          summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/*coverage.xml'

      - task: Gulp@0
        displayName: 'Package Solution'
        inputs:
          targets: 'package-solution'
          arguments: '--ship'

      - task: CopyFiles@2
        displayName: 'Copy Files to: $(Build.ArtifactStagingDirectory)'
        inputs:
          Contents: |
            sharepoint/**/*.sppkg
          TargetFolder: '$(Build.ArtifactStagingDirectory)'

      - task: PublishBuildArtifacts@1
        displayName: 'Publish Artifact: drop'

注意

如果你没有任何单元测试实现并且/或者不希望运行单元测试,则可以注释掉/删除 PublishCodeCoverageResultsPublishTestResultsnpm test 任务。

注意

可在示例中找到此文件的最新版本

实现持续部署

以下 YAML 模板介绍了持续部署阶段。 将下面的内容复制到名为 azure-pipelines-deploy-template.yml 的项目的根目录处的一个新文件中。

parameters:
  # unique name of the job
  job_name: deploy_sppkg
  # friendly name of the job
  display_name: Upload & deploy *.sppkg to SharePoint app catalog
  # name of target environment deploying to
  target_environment: ''
  # app catalog scope (tenant|sitecollection)
  m365cli_app_catalog_scope: 'tenant'
  variable_group_name: ''
jobs:
- deployment: ${{ parameters.job_name }}
  displayName: ${{ parameters.display_name }}
  pool:
    vmImage: 'ubuntu-latest'
  environment: ${{ parameters.target_environment }}
  variables:
  - group: ${{parameters.variable_group_name}} #m365_user_login, m365_user_password, m365_app_catalog_site_url
  strategy:
    runOnce:
      deploy:
        steps:
        - checkout: none
        - download: current
          artifact: drop
          patterns: '**/*.sppkg'
        - script: sudo npm install --global @pnp/cli-microsoft365
          displayName: Install CLI for Microsoft365
        - script: m365 login $(m365_app_catalog_site_url) --authType password --userName $(m365_user_login) --password $(m365_user_password)
          displayName: Login to Microsoft 365
        - script: |
            CMD_GET_SPPKG_NAME=$(find $(Pipeline.Workspace)/drop -name '*.sppkg' -exec basename {} \;)
            echo "##vso[task.setvariable variable=SpPkgFileName;isOutput=true]${CMD_GET_SPPKG_NAME}"
          displayName: Get generated *.sppkg filename
          name: GetSharePointPackage
        - script: m365 spo app add --filePath "$(Pipeline.Workspace)/drop/sharepoint/solution/$(GetSharePointPackage.SpPkgFileName)" --appCatalogUrl $(m365_app_catalog_site_url) --scope ${{ parameters.m365cli_app_catalog_scope }} --overwrite
          displayName: Upload SharePoint package to Site Collection App Catalog
        - script: m365 spo app deploy --name $(GetSharePointPackage.SpPkgFileName) --appCatalogUrl $(m365_app_catalog_site_url) --scope ${{ parameters.m365cli_app_catalog_scope }}
          displayName: Deploy SharePoint package

注意

可在示例中找到此文件的最新版本

定义管道结构

生成和部署阶段已在其各自的模板中进行了定义,因此需要将其汇编为多级管道。 本文将介绍管道的结构以及正在使用的不同环境。 将下面的内容复制到名为 azure-pipelines.yml 的项目的根目录处的一个新文件中。

name: $(TeamProject)_$(BuildDefinitionName)_$(SourceBranchName)_$(Date:yyyyMMdd)$(Rev:.r)
resources:
- repo: self

trigger:
  branches:
    include:
    - master
    - develop

stages:
- stage: build
  displayName: build
  jobs:
    - template: ./azure-pipelines-build-template.yml
      parameters:
        name: 'buildsolution'
- stage: 'deployqa'
  # uncomment if you want deployments to occur only for a specific branch
  #condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/develop'))
  jobs:
    - template: ./azure-pipelines-deploy-template.yml
      parameters:
        job_name: deploy_solution
        target_environment: 'qa'
        variable_group_name: qa_configuration

注意

可在示例中找到此文件的最新版本

注意

可通过复制 deployqa 阶段和提供不同的参数来定义多个环境。 如果执行此操作,请确保阶段名称、作业名称、目标环境和可变组名称是唯一的。

注意

可以有条件地部署到利用各种条件的不同环境中

为环境配置凭据

出于安全考虑,机密决不能提交到存储库。 上述步骤中描述的管道使用变量组将配置值保留为机密。 需要为每个环境创建变量组,并且名称需与管道定义中所述的名称匹配(此处为 qa_configuration)。 若要创建变量组,请按照下列步骤操作:

  1. 登录 Azure DevOps,导航到你的项目
  2. 在“管道”下,选择“库”
  3. 添加新的变量组,确保名称与管道定义中定义的名称相同
  4. 将以下变量添加到组中,然后选择“保存”
    • m365_user_login:SharePoint 租户管理员的用户登录名
    • m365_user_password:帐户的用户密码
    • m365_app_catalog_site_url:应用程序目录网站集的 URL

注意

可以选择变量值输入旁的挂锁图标,将其标记为“敏感”,并让 Azure DevOps 对其他用户和日志隐藏该值。