tinglesoftware / dependabot-azure-devops

Tools for updating dependencies in Azure DevOps repositories using https://dependabot.com
MIT License
182 stars 59 forks source link

Question targetRepositoryName is set but configuration cannot be found #1095

Closed LockTar closed 3 weeks ago

LockTar commented 2 months ago

I'm trying to setup a pipeline for multiple repositories. My setup is as follow:

Repo 1: config file: .azuredevops/dependabot.yml pipeline yaml file:

- task: dependabot@1
  displayName: repo 2
  inputs:
    packageManager: 'nuget'
    targetBranch: 'main'
    targetRepositoryName: 'repo 2 name'
    openPullRequestsLimit: 1

Repo 2: config file: .azuredevops/dependabot.yml

I'm getting the error: Configuration file not found at possible locations: /.azuredevops/dependabot.yml, /.azuredevops/dependabot.yaml, /.github/dependabot.yaml, /.github/dependabot.yml

When I set system.debug to true I see the following log:

##[debug]Attempting to fetch configuration file via REST API ...
##[debug]GET https://dev.azure.com/foo/bar/_apis/git/repositories/repo2/items?path=/.azuredevops/dependabot.yml
##[debug]No configuration file at 'https://dev.azure.com/foo/bar/_apis/git/repositories/repo2/items?path=/.azuredevops/dependabot.yml'

But when I navigate to that url the file is downloaded. How can that be?

LockTar commented 2 months ago

I found out that using a service connection (parameter azureDevOpsServiceConnection) does work. It must have something to do with the accesstoken of SystemVssConnection.

This works:

- task: dependabot@1
  inputs:
    packageManager: 'nuget'
    targetRepositoryName: 'repo2'
    dockerImageTag: '1.24' # another open issue in this repo
    azureDevOpsServiceConnection: myconnection

This doesn't:

- task: dependabot@1
  inputs:
    packageManager: 'nuget'
    targetRepositoryName: 'repo2'
    dockerImageTag: '1.24' # another open issue in this repo
LockTar commented 2 months ago

I have set all permissions to allow on the Project collection service account but doesn't help.

mburumaxwell commented 2 months ago

The error No configuration file at '....' is only written out when the response is 404 (NotFound). Authentication issues (401 and 403) should print different logs. See below:

https://github.com/tinglesoftware/dependabot-azure-devops/blob/4ffc72b2d85f4fa1f04ad9f47f63188ccff43920/extension/task/utils/parseConfigFile.ts#L68-L82

LockTar commented 2 months ago

I see it. This is then very strange. Can it be something with dockerImageTag: '1.24'? I've done this because of issue #921.

Again, when I click the link that is logged by the error, the configuration file is downloaded. Enabling the service connection (only change) works.

This is my complete setup:

My pipeline:

trigger: none
schedules:
- cron: '0 2 * * *'
  always: true
  branches:
    include:
      - main
  batch: true
  displayName: Nightly

variables:
  # Define the system.debug variable
  system.debug: true

parameters:
  - name: myObject
    type: object
    default:
      repos:
        - 'my.repo2'

stages:
- stage: dependabot
  displayName: dependabot
  pool:
    name: Azure Pipelines
    vmImage: ubuntu-latest

  jobs:
  - job: dependabot
    displayName: Run dependabot
    steps:
    - ${{ each repo in parameters.myObject.repos }}:
      - task: dependabot@1
        displayName: ${{ repo }}
        continueOnError: true
        inputs:
          targetRepositoryName: ${{ repo }}
          # azureDevOpsServiceConnection: my-service-connection # without service connection configuration file can't be found.
          dockerImageTag: '1.24' # https://github.com/tinglesoftware/dependabot-azure-devops/issues/921
        env:
          AZURE_ARTIFACTS_TOKEN: $(System.AccessToken)

In repo 2 config .azuredevops/dependabot.yml:

version: 2
registries:
  foo:
    type: nuget-feed
    url: https://pkgs.dev.azure.com/MyCollection/MyProject/_packaging/foo/nuget/v3/index.json
    token: PAT:${{AZURE_ARTIFACTS_TOKEN}}
updates:
  - package-ecosystem: nuget
    registries:
    - foo
    directory: "/"
    target-branch: main
    commit-message:
      prefix: fix
      include: scope
    ignore:
      - dependency-name: "*"
        update-types: ["version-update:semver-major", "version-update:semver-minor"]

Output log:

##[debug]loading INPUT_TARGETREPOSITORYNAME
##[debug]loading INPUT_DOCKERIMAGETAG
##[debug]loading INPUT_FORWARDHOSTSSHSOCKET
##[debug]loading ENDPOINT_AUTH_SYSTEMVSSCONNECTION
##[debug]loading ENDPOINT_AUTH_SCHEME_SYSTEMVSSCONNECTION
##[debug]loading ENDPOINT_AUTH_PARAMETER_SYSTEMVSSCONNECTION_ACCESSTOKEN
##[debug]loading SECRET_SYSTEM_ACCESSTOKEN
##[debug]loaded 14
##[debug]Agent.ProxyUrl=undefined
##[debug]Agent.CAInfo=undefined
##[debug]Agent.ClientCert=undefined
##[debug]Agent.SkipCertValidation=undefined
##[debug]useConfigFile=true
##[debug]Checking for docker install ...
##[debug]which 'docker'
##[debug]found: '/usr/bin/docker'
##[debug]System.TeamFoundationCollectionUri=https://dev.azure.com/MyCollection/
##[debug]System.TeamProject=MyProject
##[debug]targetRepositoryName=my.repo2
##[debug]gitHubAccessToken=undefined
##[debug]gitHubConnection=undefined
##[debug]azureDevOpsUser=undefined
##[debug]azureDevOpsAccessToken=undefined
##[debug]azureDevOpsServiceConnection=undefined
##[debug]No custom token provided. The SystemVssConnection's AccessToken shall be used.
##[debug]SystemVssConnection auth param AccessToken = ***
##[debug]setAutoComplete=false
##[debug]mergeStrategy=squash
##[debug]autoCompleteIgnoreConfigIds=undefined
##[debug]autoApprove=false
##[debug]autoApproveUserToken=undefined
##[debug]failOnException=true
##[debug]excludeRequirementsToUnlock=undefined
##[debug]updaterOptions=undefined
##[debug]targetUpdateIds=undefined
##[debug]securityAdvisoriesFile=undefined
##[debug]skipPullRequests=false
##[debug]abandonUnwantedPullRequests=false
##[debug]extraEnvironmentVariables=undefined
##[debug]forwardHostSshSocket=false
##[debug]dockerImageTag=1.24
##[debug]Attempting to fetch configuration file via REST API ...
##[debug]GET https://dev.azure.com/MyCollection/MyProject/_apis/git/repositories/my.repo2/items?path=/.azuredevops/dependabot.yml
##[debug]No configuration file at 'https://dev.azure.com/MyCollection/MyProject/_apis/git/repositories/my.repo2/items?path=/.azuredevops/dependabot.yml'
##[debug]GET https://dev.azure.com/MyCollection/MyProject/_apis/git/repositories/my.repo2/items?path=/.azuredevops/dependabot.yaml
##[debug]No configuration file at 'https://dev.azure.com/MyCollection/MyProject/_apis/git/repositories/my.repo2/items?path=/.azuredevops/dependabot.yaml'
##[debug]GET https://dev.azure.com/MyCollection/MyProject/_apis/git/repositories/my.repo2/items?path=/.github/dependabot.yaml
##[debug]No configuration file at 'https://dev.azure.com/MyCollection/MyProject/_apis/git/repositories/my.repo2/items?path=/.github/dependabot.yaml'
##[debug]GET https://dev.azure.com/MyCollection/MyProject/_apis/git/repositories/my.repo2/items?path=/.github/dependabot.yml
##[debug]No configuration file at 'https://dev.azure.com/MyCollection/MyProject/_apis/git/repositories/my.repo2/items?path=/.github/dependabot.yml'
##[debug]task result: Failed
##[error]Configuration file not found at possible locations: /.azuredevops/dependabot.yml, /.azuredevops/dependabot.yaml, /.github/dependabot.yaml, /.github/dependabot.yml
LockTar commented 2 months ago

Are we sure that when a user (in our example the build service) is getting a 403 or a 401 with azure devops rest api when it's trying to get a file that it hasn't permissions to? I think it's masked as a 404.

I also tried something else for more debugging. When I use azureDevOpsServiceConnection, a PAT has to be set in the service connection. When I remove the claim for repository read, the configuration cannot be found as well.

So that is the reason why I think the rest client is returning a 404 when the user has not enough permissions.

Lukejkw commented 1 month ago

I can confirm that this is a permissions issue due to the Access Token being scoped to the build pipeline.

Import to turn off "Protect access to repositories in YAML pipelines"

The following settings worked for me:

image

LockTar commented 3 weeks ago

@Lukejkw Thank you for the reply. I checked this setting and it brought me in the right direction. This option is of course for safety so it's not recommended to turn it off. It's on by default and mostly forced on organization/collection level.

So I digged into it because turning this setting off made it working. But! I found a better workaround. I now knew the reason so it's easier to search for it.

If you read the documentation for the setting Protect access to repositories in YAML pipelines here and here it states that a yaml pipeline by default can't access another repo (in same or another project) because of that setting.

But you can use the checkout step or a uses statement in your pipeline to connect to another repository. We don't need the code for this dependabot task to work so I went for uses. This gave me the error Job 'Job1' references the repository 'R1' which is not defined by the pipeline.. On StackOverflow I found the solution for this. Apparently you also need to use the resources statement. Sample:

resources:
  repositories:
  - repository: R1
    type: git
    name: MyDevOpsProject/R1
  - repository: R2
    type: git
    name: MyDevOpsProject/R2
  - repository: R3
    type: git
    name: MyDevOpsProject/R3
  - repository: Rnnn
    type: git
    name: MyDevOpsProject/Rnnn

So I ended with the following pipeline:

trigger: none
schedules:
- cron: '0 2 * * *'
  always: true
  branches:
    include:
      - main
  batch: true
  displayName: Nightly

variables:
  # Define the system.debug variable
  system.debug: true

parameters:
  - name: repositories
    displayName: Repositories
    type: object
    default:
      names:
        - 'my.repo2'

resources:
  repositories:
  - repository: my.repo2
    type: git
    name: my.repo2 # I didn't use project because repo is in the same project

stages:
- stage: dependabot
  displayName: dependabot
  pool:
    name: Azure Pipelines
    vmImage: ubuntu-latest

  jobs:
  - job: dependabot
    displayName: Run dependabot

    uses:
      repositories: # List of referenced repositories
      - 'my.repo2' # Repository reference from the resources section

# or
    # uses:
      # repositories: ${{ parameters.repositories.names }}

    steps:
    - ${{ each repo in parameters.repositories.names }}:
      - task: dependabot@1
        displayName: ${{ repo }}
        continueOnError: true
        inputs:
          targetRepositoryName: ${{ repo }}
          dockerImageTag: '1.24' # https://github.com/tinglesoftware/dependabot-azure-devops/issues/921
        env:
          AZURE_ARTIFACTS_TOKEN: $(System.AccessToken)

When you queue the pipeline, you need to Permit the pipeline to access the repository. You will have to do that for every repository.

Only need to find a way to remove the duplicate repository names here in the pipeline.