Избегайте git clean с помощью собственного агента сборки Azure Devops

У меня есть сценарий сборки YAML в репозитории git, размещенном в Azure, который запускается через 7 агентов сборки, работающих на локальной виртуальной машине. Каждый раз, когда это запускается, сборка выполняет git clean, что занимает значительное время из-за большой node_modules папки, очистка которой занимает много времени.

Страница MSDN здесь, кажется, предполагает, что это можно настроить, но не показывает подробностей о том, как это настроить. Я не могу сказать, следует ли указывать этот параметр в агенте, в сценарии YAML, в DevOps на конвейере или где.

Есть ли какая-то другая документация, которую мне не хватает, или это невозможно?

Обновление: начало файла YAML находится здесь:

variables:
  BUILD_VERSION: 1.0.0.$(Build.BuildId)
  buildConfiguration: 'Release'
  process.clean: false

jobs:
###### ######################################################
###### 1 - Build and publish .NET
#############################################################

- job: net_build_publish
  displayName: .NET build and publish
  pool:
    name: default
  steps:
  - script: echo $(BUILD_VERSION)

  - task: DotNetCoreCLI@2
    displayName: dotnet build $(buildConfiguration)
    inputs:
      command: 'build'
      projects: |
        myrepo/**/API/*.csproj
      arguments: '-c $(buildConfiguration) /p:Version=$(BUILD_VERSION)'

Полный yaml намного длиннее, но вывод первого задания включает этот вывод в Checkout задачу

Checkout myrepo@master to s

View raw log

Starting: Checkout myrepo@master to s
==============================================================================
Task         : Get sources
Description  : Get sources from a repository. Supports Git, TfsVC, and SVN repositories.
Version      : 1.0.0
Author       : Microsoft
Help         : [More Information](https://go.microsoft.com/fwlink/?LinkId=798199)
==============================================================================
Syncing repository: myrepo (Git)
Prepending Path environment variable with directory containing 'git.exe'.
git version
git version 2.26.2.windows.1
git lfs version
git-lfs/2.11.0 (GitHub; windows amd64; go 1.14.2; git 48b28d97)
git config --get remote.origin.url
git clean -ffdx
Removing myrepo/Data/Core/API/bin/
Removing myrepo/Data/Core/API/customersettings.json
Removing myrepo/Data/Core/API/obj/
Removing myrepo/Data/Core/Shared/bin/
Removing myrepo/Data/Core/Shared/obj/
....

У нас есть еще одно задание, которое запускает npm install и npm build для проекта Angular, и каждая сборка в конвейере занимает 5 минут для выполнения шага установки npm, возможно, из-за этого git clean при получении репозитория?


comment
Попробуйте добавить: steps: - checkout: self clean: false или: - job: myJob workspace: clean: false   -  person Shayki Abramczyk    schedule 30.09.2020


Ответы (2)


Как я уже упоминал ниже. Перед запуском npm install необходимо вычислить хэш. Если хэш совпадает с хешем, близким к node_modules, вы можете пропустить установку зависимостей. Это может помочь вам добиться этого:

steps:
- task: PowerShell@2
  displayName: 'Calculate and save packages.config hash'
  inputs:
    targetType: 'inline'
    pwsh: true
    script: |
      # generates a hash of package-lock.json
      $newHash = Get-FileHash -Algorithm MD5 -Path (Get-ChildItem package-lock.json)
      $hashPath = "$(System.DefaultWorkingDirectory)/cache-npm/hash.txt"
      if(Test-Path -path $hashPath) {
        if(Compare-Object -ReferenceObject $(Get-Content $hashPath) -DifferenceObject $newHash) {
          
          Write-Host "##vso[task.setvariable variable=NodeModulesAreUpToDate;]true"
          $newHash > $hashPath
          Write-Host ("Hash File saved to " + $hashPath)
        } else {
          # files are the same
          Write-Host "no need to install node_modules"
        }
      } else {
        $newHash > $hashPath
        Write-Host ("Hash File saved to " + $hashPath)
      }
      
      $storedHash = Get-Content $hashPath
      Write-Host $storedHash
    workingDirectory: '$(System.DefaultWorkingDirectory)/cache-npm'

- script: npm install
  workingDirectory: '$(Build.SourcesDirectory)/cache-npm'
  condition: ne(variables['NodeModulesAreUpToDate'], true)
person Krzysztof Madej    schedule 30.09.2020
comment
Предположим, у вас есть две ветки, A и B. Вы обновляете версии на B. Вы нажимаете B. Конвейер, который выполняет установку NPM, запускается на Агенте 1 из 7. Он обновляется. Вы обновляете B и нажимаете. Его подхватывает агент 2. Установка npm не выполняется, не ошиблись ли версии? Скажем, вы теперь отправляете изменения в A, которые не включают блокировку пакета. Агент 1 поднимает его. Нет установки npm, но он был ранее обновлен первоначальным нажатием B. Этот сценарий звучит правдоподобно? Не вызовет ли это решение проблем с версией? - person Matt; 30.09.2020
comment
Для этого вам нужно хешировать свой package-lock.json и держать его близко к каталогу node_modules. Каждый раз, когда вы запускаете конвейер, вам нужно вычислять хэш текущего файла и сравнивать его с хешем, хранящимся в файловой системе. Если они отличаются, вы запускаете npm install и обновляете хеш. Если хеш такой же, вы пропустите установку npm. Таким образом, вы получите единственный конвейер. Позже я обновлю свой ответ, так как этот подход кажется лучше. - person Krzysztof Madej; 30.09.2020
comment
Вы можете проверить мой отредактированный ответ? В настоящий момент у меня не может быть агента с собственным хостингом, чтобы протестировать его, но он должен сработать для вас. - person Krzysztof Madej; 01.10.2020
comment
Выглядит обнадеживающе! Я протестирую на следующей неделе - спасибо за ваш вклад - person JLo; 01.10.2020
comment
@JLo, пожалуйста, дайте мне знать, как только вы его протестируете, и добро пожаловать :) - person Krzysztof Madej; 01.10.2020

git clean -ffdx удалит любые изменения в источнике, не отслеживаемые системой управления версиями. Вы можете попробовать конвейерное кэширование, что может помочь сократить время сборки, позволяя повторно использовать выходные данные или загруженные зависимости из одного запуска в последующих запусках, тем самым снижая или избегая затрат на воссоздание или повторную загрузку тех же файлов снова. Проверьте следующую ссылку:

https://docs.microsoft.com/en-us/azure/devops/pipelines/release/caching?view=azure-devops#nodejsnpm

variables:
  npm_config_cache: $(Pipeline.Workspace)/.npm

steps:
- task: Cache@2
  inputs:
    key: 'npm | "$(Agent.OS)" | package-lock.json'
    restoreKeys: |
       npm | "$(Agent.OS)"
    path: $(npm_config_cache)
  displayName: Cache npm
person Cece Dong - MSFT    schedule 01.10.2020