Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for ignore conditions using .github/dependabot.yml file. #582

Closed
wants to merge 1 commit into from

Conversation

assi010
Copy link

@assi010 assi010 commented Mar 27, 2023

Currently the ignore value (docs) is not being read from the .github/dependabot.yml file.

I updated the extension so that this value will now be used to set the DEPENDABOT_IGNORE_CONDITIONS environment variable.

@mburumaxwell
Copy link
Contributor

@assi010 the ignore conditions are automatically picked up from the configuration file in the ruby script.

See

puts "Looking for configuration file in the repository ..."
$config_file = begin
# Using fetcher_args as before or in the examples will result in the
# config file not being found if the directory specified is not the root.
# This happens because the files are checked relative to the supplied directory.
# https://github.com/dependabot/dependabot-core/blob/c5cd618812b07ece4a4b53ea18d80ad213b077e7/common/lib/dependabot/config/file_fetcher.rb#L29
#
# To solve this, the FileFetcher for the Config should have its own source
# with the directory pointing to the root. Cloning makes it much easier
# since we are only making the change for fetching the config file.
#
# See https://github.com/tinglesoftware/dependabot-azure-devops/issues/399
cfg_source = $source.clone
cfg_source.directory = "/"
cfg_file = Dependabot::Config::FileFetcher.new(
source: cfg_source,
credentials: $options[:credentials],
options: $options[:updater_options]
).config_file
puts "Using configuration file at '#{cfg_file.path}' 😎"
Dependabot::Config::File.parse(cfg_file.content)
rescue Dependabot::RepoNotFound, Dependabot::DependencyFileNotFound
puts "Configuration file was not found, a default config will be used. 😔"
Dependabot::Config::File.new(updates: [])
end
$update_config = $config_file.update_config(
$package_manager,
directory: $options[:directory],
target_branch: $options[:branch]
)

and also

def ignored_versions_for(dep)
if $options[:ignore_conditions].any?
ignore_conditions = $options[:ignore_conditions].map do |ic|
Dependabot::Config::IgnoreCondition.new(
dependency_name: ic["dependency-name"],
versions: ic["versions"],
update_types: ic["update-types"]
)
end
Dependabot::Config::UpdateConfig.new(ignore_conditions: ignore_conditions).
ignored_versions_for(
dep,
security_updates_only: $options[:security_updates_only]
)
else
$update_config.ignored_versions_for(
dep,
security_updates_only: $options[:security_updates_only]
)
end
end

@assi010
Copy link
Author

assi010 commented Mar 27, 2023

Thanks for explaining @mburumaxwell.

I used the Azure Devops extension with the following dependabot.yml configuration:

version: 2
updates:
  - package-ecosystem: "nuget"
    directory: "/"
    schedule:
      interval: "daily"
    open-pull-requests-limit: 3
    ignore:
      - dependency-name: "*"
        update-types: [ "version-update:semver-major" ]

However, it would still create pull requests for packages updating them from version 6.x.x to 7.x.x. After adding the DEPENDABOT_IGNORE_CONDITIONS environment variable the issue was resolved, which lead to creating this PR.

I'll do another check just to be sure I didn't misconfigure anything on my end.

@assi010
Copy link
Author

assi010 commented Mar 29, 2023

@mburumaxwell

I have made a new project in Azure Devops with a sample dotnet Api.

.github/dependabot.yml:

version: 2
updates:
  - package-ecosystem: "nuget"
    directory: "/"
    schedule:
      interval: "daily"
    open-pull-requests-limit: 3
    ignore:
      - dependency-name: "*"
        update-types: [ "version-update:semver-major" ]

pipeline.yaml:

trigger: none # Disable CI trigger

schedules:
  - cron: '0 2 * * *' # daily at 2am UTC
    always: true # run even when there are no code changes
    branches:
      include:
        - main
    batch: true
    displayName: Daily

pool:
  vmImage: 'ubuntu-latest'

steps:
  - task: dependabot@1

TestApi.csproj:

<Project Sdk="Microsoft.NET.Sdk.Web">

    <PropertyGroup>
        <TargetFramework>net6.0</TargetFramework>
        <Nullable>enable</Nullable>
        <ImplicitUsings>enable</ImplicitUsings>
    </PropertyGroup>

    <ItemGroup>
      <PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
    </ItemGroup>
</Project>

Running the pipeline my expectation is that it will ignore the package upgrade to 7.0.0.
However, it still creates the following PR :
image

image

In the pipeline logs I can see docker being run with the following environment variables:

/usr/bin/docker run --rm -i 
    -e DEPENDABOT_PACKAGE_MANAGER=nuget 
    -e DEPENDABOT_OPEN_PULL_REQUESTS_LIMIT=5 
    -e DEPENDABOT_DIRECTORY=/ 
    -e DEPENDABOT_FAIL_ON_EXCEPTION=true 
    -e AZURE_ORGANIZATION=*** 
    -e AZURE_PROJECT=Test 
    -e AZURE_REPOSITORY=Test 
    -e AZURE_ACCESS_TOKEN=*** 
    -e AZURE_MERGE_STRATEGY=squash 
    ghcr.io/tinglesoftware/dependabot-updater:0.16

As you can see the values from the dependabot.yml are being set as environment variables, but the ignore conditions are missing.

To be clear I have a limited understanding of ruby so I might be missing something, but this is the only place where I saw the $options[:ignore_conditions] being assigned, which is from the environment variable.

##################################################################################################
# Setup Ignore conditions #
# DEPENDABOT_IGNORE_CONDITIONS Example: [{"dependency-name":"ruby","versions":[">= 3.a", "< 4"]}]
##################################################################################################
unless ENV["DEPENDABOT_IGNORE_CONDITIONS"].to_s.strip.empty?
$options[:ignore_conditions] = JSON.parse(ENV.fetch("DEPENDABOT_IGNORE_CONDITIONS", nil))
end

The extension does set all the other environment variables that it parsed from the dependabot.yml configuration. For example the allow conditions:

// Set the dependencies to allow
let allow = update.allow;
if (allow) {
dockerRunner.arg(["-e", `DEPENDABOT_ALLOW_CONDITIONS=${allow}`]);
}

From what I could tell only the ignore conditions are not being set in the extension. Which is why I added them.

@DaleMckeown
Copy link

@assi010 I've definitely had semver blocking working before, infact it was the only way I could figure out how to do it until I finally cracked how to do it with versions specifically.

This was previously working for me:

    - dependency-name: 'Microsoft.EntityFrameworkCore.Relational'
       update-types: ['version-update:semver-major']

I suspect that the dependency-name being a wildcard might be the problem. As a test, you could try targeting a package or two explicitly, and see what happens.

The issue i opened on dependabot core is here: dependabot/dependabot-core#6873

@assi010
Copy link
Author

assi010 commented Apr 4, 2023

@DaleMckeown I'll definitely try that, thanks for the suggestion!

But isn't it weird that the extension sets all values it parses from dependabot.yml as environment variables to the docker image, yet it omits the ignore conditions?

image

Allow conditions and ignore conditions are both optional with a JSON value according to the docs in this repo.

allow: update["allow"] ? JSON.stringify(update["allow"]) : undefined,

Here the allow value is parsed from the config file by the extension.

let allow = update.allow;
if (allow) {
dockerRunner.arg(["-e", `DEPENDABOT_ALLOW_CONDITIONS=${allow}`]);
}

And here it is used to set as environment variable for the docker image.

The ignore conditions are never set. However, when I set them as the environment variable everything worked as expected.

In the documentation of dependabot it even gives dependency-name: "*" as a valid example:

image

Considering it works with the environment variable and that the example configuration is valid according to the docs, I am a little skeptical that this is really the issue.

@mburumaxwell
Copy link
Contributor

DEPENDABOT_IGNORE_CONDITIONS is only meant to override, and currently a remnant of when we did not have proper support for the configuration file. DEPENDABOT_ALLOW_CONDITIONS exists because the upstream currently does not have a similar concept. Nothing wrong or odd with that.

That said, I just pulled a configuration file from one of our projects that uses ignores, wildcards, and I know it works because I wrote it:

# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates

version: 2
updates:
- package-ecosystem: "nuget" # See documentation for possible values
  directory: "/" # Location of package manifests
  schedule:
    interval: "daily"
    time: "00:00"
  open-pull-requests-limit: 10
  ignore:
  # Ignore patch updates for some packages
  - dependency-name: "Microsoft.*"
    update-types: ["version-update:semver-patch"]
  - dependency-name: "System.*"
    update-types: ["version-update:semver-patch"]
  - dependency-name: "MongoDB.*"
    update-types: ["version-update:semver-patch"]
  - dependency-name: "Moq"
    update-types: ["version-update:semver-patch"]

But for clarity sake, I have created a repro from what you provided. The package does not get updated.

Did I miss anything?

@assi010
Copy link
Author

assi010 commented Apr 8, 2023

Thanks for the provided repro, it finally led me to the real issue at play here.

I looked at your project and tried to reproduce it in my own Azure Devops project once again, however this time it worked perfectly. I thought I was losing my mind..

I compared my previous repro project and the current one. On my Windows machine the dependabot.yml was created as UTF-8 BOM, while on my linux machine it was created as UTF-8.

Turns out that on the UTF-8 BOM version the ignore conditions are not picked up properly, while it works fine on UTF-8. That is why I started looking into the environment variables, as it worked completely fine when using the environment variables together with UTF-8 BOM.

Change:
image

Pipeline with dependabot.yml as UTF-8
image

Pipeline with dependabot.yml as UTF-8 BOM
image

After removing the BOM from my dependabot.yml in my existing project, the conditions are picked up as expected as you can see.

Sorry for insisting on my changes @mburumaxwell @DaleMckeown, turns out my "fix" was just a workaround for a whole other issue 😅. Thanks for the help.

@assi010 assi010 closed this Apr 8, 2023
@mburumaxwell
Copy link
Contributor

I doubt these are as related. Maybe if your pipeline has other things going on.
Glad it's working now.

@assi010
Copy link
Author

assi010 commented Apr 9, 2023

I doubt these are as related. Maybe if your pipeline has other things going on. Glad it's working now.

That makes sense, but I am able to consistently reproduce the issue with your example using Azure hosted agents.
Just remove the top 5 lines of your dependabot.yml so that it starts with the version line at the top, add BOM and it will stop ignoring version 7.x.x updates.

I have created a public repro as well in case you're interested.

I imported your example and tested the following scenarios:

  • Import baseline #1
  • Add BOM to dependabot.yml #2
  • Remove comments from dependabot.yml #3 (This one doesn't handle ignore properly)
  • Remove BOM from dependabot.yml #4

@mburumaxwell
Copy link
Contributor

This is a curious case. It could either be the BOM or the comments.

@mburumaxwell
Copy link
Contributor

Possibly related to dependabot/dependabot-core#6714

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants