Skip to content

Commit

Permalink
Add support for docker-compose.yml files (#11492)
Browse files Browse the repository at this point in the history
  • Loading branch information
robaiken authored Feb 19, 2025
1 parent 1213dc1 commit ffd081f
Show file tree
Hide file tree
Showing 183 changed files with 16,224 additions and 415 deletions.
3 changes: 3 additions & 0 deletions .github/ci-filters.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ devcontainers:
docker:
- *shared
- 'docker/**'
docker_compose:
- *shared
- 'docker_compose/**'
dotnet_sdk:
- *shared
- 'dotnet_sdk/**'
Expand Down
3 changes: 3 additions & 0 deletions .github/issue-labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
"L: docker":
- '(docker|kubernetes)'

"L: docker:compose":
- '(docker_compose)'

"L: elm":
- '(elm)'

Expand Down
4 changes: 4 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
- changed-files:
- any-glob-to-any-file: docker/**

"L: docker:compose":
- changed-files:
- any-glob-to-any-file: docker_compose/**

"L: dotnet-sdk":
- changed-files:
- any-glob-to-any-file: dotnet_sdk/**
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ jobs:
- { path: common, name: common, ecosystem: common}
- { path: composer, name: composer, ecosystem: composer }
- { path: docker, name: docker, ecosystem: docker }
- { path: docker_compose, name: docker_compose, ecosystem: docker_compose }
- { path: dotnet_sdk, name: dotnet_sdk, ecosystem: dotnet-sdk }
- { path: elm, name: elm, ecosystem: elm }
- { path: git_submodules, name: git_submodules, ecosystem: gitsubmodule }
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/images-branch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ jobs:
- { name: cargo, ecosystem: cargo }
- { name: composer, ecosystem: composer }
- { name: docker, ecosystem: docker }
- { name: docker_compose, ecosystem: docker_compose }
- { name: dotnet_sdk, ecosystem: dotnet-sdk }
- { name: elm, ecosystem: elm }
- { name: git_submodules, ecosystem: gitsubmodule }
Expand Down
3 changes: 2 additions & 1 deletion Dockerfile.updater-core
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ COPY --chown=dependabot:dependabot cargo/.bundle cargo/dependabot-cargo.gemspec
COPY --chown=dependabot:dependabot composer/.bundle composer/dependabot-composer.gemspec composer/
COPY --chown=dependabot:dependabot devcontainers/.bundle devcontainers/dependabot-devcontainers.gemspec devcontainers/
COPY --chown=dependabot:dependabot docker/.bundle docker/dependabot-docker.gemspec docker/
COPY --chown=dependabot:dependabot docker_compose/.bundle docker_compose/dependabot-docker_compose.gemspec docker_compose/
COPY --chown=dependabot:dependabot dotnet_sdk/.bundle dotnet_sdk/dependabot-dotnet_sdk.gemspec dotnet_sdk/
COPY --chown=dependabot:dependabot elm/.bundle elm/dependabot-elm.gemspec elm/
COPY --chown=dependabot:dependabot git_submodules/.bundle git_submodules/dependabot-git_submodules.gemspec git_submodules/
Expand All @@ -107,7 +108,7 @@ COPY --chown=dependabot:dependabot swift/.bundle swift/dependabot-swift.gemspec
COPY --chown=dependabot:dependabot terraform/.bundle terraform/dependabot-terraform.gemspec terraform/

# prevent having all the source in every ecosystem image
RUN for ecosystem in git_submodules terraform github_actions hex elm docker nuget maven gradle cargo composer go_modules python pub npm_and_yarn bundler silent swift devcontainers dotnet_sdk bun; do \
RUN for ecosystem in git_submodules terraform github_actions hex elm docker docker-compose nuget maven gradle cargo composer go_modules python pub npm_and_yarn bundler silent swift devcontainers dotnet_sdk bun; do \
mkdir -p $ecosystem/lib/dependabot; \
touch $ecosystem/lib/dependabot/$ecosystem.rb; \
done
Expand Down
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ gem "dependabot-common", path: "common"
gem "dependabot-composer", path: "composer"
gem "dependabot-devcontainers", path: "devcontainers"
gem "dependabot-docker", path: "docker"
gem "dependabot-docker_compose", path: "docker_compose"
gem "dependabot-dotnet_sdk", path: "dotnet_sdk"
gem "dependabot-elm", path: "elm"
gem "dependabot-github_actions", path: "github_actions"
Expand Down
7 changes: 7 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ PATH
dependabot-devcontainers (0.297.0)
dependabot-common (= 0.297.0)

PATH
remote: docker_compose
specs:
dependabot-docker_compose (0.297.0)
dependabot-common (= 0.297.0)

PATH
remote: docker
specs:
Expand Down Expand Up @@ -391,6 +397,7 @@ DEPENDENCIES
dependabot-composer!
dependabot-devcontainers!
dependabot-docker!
dependabot-docker_compose!
dependabot-dotnet_sdk!
dependabot-elm!
dependabot-git_submodules!
Expand Down
1 change: 1 addition & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ GEMSPECS = %w(
devcontainers/dependabot-devcontainers.gemspec
dotnet_sdk/dependabot-dotnet_sdk.gemspec
bun/dependabot-bun.gemspec
docker_compose/dependabot-docker_compose.gemspec
).freeze

def run_command(command)
Expand Down
5 changes: 5 additions & 0 deletions bin/docker-dev-shell
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,11 @@ docker run --rm -ti \
-v "$(pwd)/docker/lib:$CODE_DIR/docker/lib" \
-v "$(pwd)/docker/script:$CODE_DIR/docker/script" \
-v "$(pwd)/docker/spec:$CODE_DIR/docker/spec" \
-v "$(pwd)/docker_compose/.rubocop.yml:$CODE_DIR/docker_compose/.rubocop.yml" \
-v "$(pwd)/docker_compose/dependabot-docker_compose.gemspec:$CODE_DIR/docker_compose/dependabot-docker_compose.gemspec" \
-v "$(pwd)/docker_compose/lib:$CODE_DIR/docker_compose/lib" \
-v "$(pwd)/docker_compose/script:$CODE_DIR/docker_compose/script" \
-v "$(pwd)/docker_compose/spec:$CODE_DIR/docker_compose/spec" \
-v "$(pwd)/dotnet_sdk/.rubocop.yml:$CODE_DIR/dotnet_sdk/.rubocop.yml" \
-v "$(pwd)/dotnet_sdk/dependabot-dotnet_sdk.gemspec:$CODE_DIR/dotnet_sdk/dependabot-dotnet_sdk.gemspec" \
-v "$(pwd)/dotnet_sdk/lib:$CODE_DIR/dotnet_sdk/lib" \
Expand Down
3 changes: 3 additions & 0 deletions bin/dry-run.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
# - elm
# - submodules
# - docker
# - docker_compose
# - terraform
# - pub
# - swift
Expand All @@ -58,6 +59,7 @@
$LOAD_PATH << "./composer/lib"
$LOAD_PATH << "./devcontainers/lib"
$LOAD_PATH << "./docker/lib"
$LOAD_PATH << "./docker_compose/lib"
$LOAD_PATH << "./dotnet_sdk/lib"
$LOAD_PATH << "./elm/lib"
$LOAD_PATH << "./git_submodules/lib"
Expand Down Expand Up @@ -105,6 +107,7 @@
require "dependabot/composer"
require "dependabot/devcontainers"
require "dependabot/docker"
require "dependabot/docker_compose"
require "dependabot/dotnet_sdk"
require "dependabot/elm"
require "dependabot/git_submodules"
Expand Down
1 change: 1 addition & 0 deletions common/lib/dependabot/config/file.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def self.parse(config)
"composer" => "composer",
"devcontainer" => "devcontainers",
"docker" => "docker",
"docker-compose" => "docker_compose",
"dotnet-sdk" => "dotnet_sdk",
"elm" => "elm",
"github-actions" => "github_actions",
Expand Down
101 changes: 29 additions & 72 deletions docker/lib/dependabot/docker/file_fetcher.rb
Original file line number Diff line number Diff line change
@@ -1,68 +1,63 @@
# typed: strict
# frozen_string_literal: true

require "sorbet-runtime"
require "dependabot/docker/utils/helpers"
require "dependabot/file_fetchers"
require "dependabot/file_fetchers/base"
require "dependabot/shared/utils/helpers"
require "dependabot/shared/shared_file_fetcher"

module Dependabot
module Docker
class FileFetcher < Dependabot::FileFetchers::Base
class FileFetcher < Dependabot::Shared::SharedFileFetcher
extend T::Sig
extend T::Helpers

YAML_REGEXP = /^[^\.].*\.ya?ml$/i
DOCKER_REGEXP = /dockerfile|containerfile/i

sig { override.returns(Regexp) }
def self.filename_regex
DOCKER_REGEXP
end

sig { override.returns(String) }
def self.required_files_message
"Repo must contain a Dockerfile, Containerfile, or Kubernetes YAML files."
end

sig { override.params(filenames: T::Array[String]).returns(T::Boolean) }
def self.required_files_in?(filenames)
filenames.any? { |f| f.match?(DOCKER_REGEXP) } or
filenames.any? { |f| f.match?(YAML_REGEXP) }
end

private

sig { override.returns(String) }
def self.required_files_message
"Repo must contain a Dockerfile, Containerfile, or Kubernetes YAML files."
def default_file_name
"Dockerfile"
end

sig { override.returns(String) }
def file_type
"Docker"
end

sig { override.returns(T::Array[DependencyFile]) }
def fetch_files
fetched_files = []
fetched_files += correctly_encoded_dockerfiles
fetched_files += correctly_encoded_yamlfiles
fetched_files = correctly_encoded_dockerfiles
fetched_files += super

return fetched_files if fetched_files.any?

if incorrectly_encoded_dockerfiles.none? && incorrectly_encoded_yamlfiles.none?
raise Dependabot::DependencyFileNotFound.new(
File.join(directory, "Dockerfile"),
"No Dockerfiles nor Kubernetes YAML found in #{directory}"
)
elsif incorrectly_encoded_dockerfiles.none?
raise(
Dependabot::DependencyFileNotParseable,
T.must(incorrectly_encoded_yamlfiles.first).path
)
else
raise(
Dependabot::DependencyFileNotParseable,
T.must(incorrectly_encoded_dockerfiles.first).path
)
end
raise_appropriate_error(incorrectly_encoded_dockerfiles)
end

private

sig { returns(T::Array[DependencyFile]) }
def dockerfiles
@dockerfiles ||= T.let(fetch_dockerfiles, T.nilable(T::Array[DependencyFile]))
@dockerfiles ||= T.let(fetch_candidate_dockerfiles, T.nilable(T::Array[DependencyFile]))
end

sig { returns(T::Array[Dependabot::DependencyFile]) }
def fetch_dockerfiles
sig { returns(T::Array[DependencyFile]) }
def fetch_candidate_dockerfiles
repo_contents(raise_errors: false)
.select { |f| f.type == "file" && f.name.match?(DOCKER_REGEXP) }
.select { |f| f.type == "file" && f.name.match?(self.class.filename_regex) }
.map { |f| fetch_file_from_host(f.name) }
end

Expand All @@ -75,44 +70,6 @@ def correctly_encoded_dockerfiles
def incorrectly_encoded_dockerfiles
dockerfiles.reject { |f| f.content&.valid_encoding? }
end

sig { returns(T::Array[DependencyFile]) }
def yamlfiles
@yamlfiles ||= T.let(
repo_contents(raise_errors: false)
.select { |f| f.type == "file" && f.name.match?(YAML_REGEXP) }
.map { |f| fetch_file_from_host(f.name) },
T.nilable(T::Array[DependencyFile])
)
end

sig { params(resource: Object).returns(T.nilable(T::Boolean)) }
def likely_kubernetes_resource?(resource)
# Heuristic for being a Kubernetes resource. We could make this tighter but this probably works well.
resource.is_a?(::Hash) && resource.key?("apiVersion") && resource.key?("kind")
end

sig { returns(T::Array[Dependabot::DependencyFile]) }
def correctly_encoded_yamlfiles
candidate_files = yamlfiles.select { |f| f.content&.valid_encoding? }
candidate_files.select do |f|
if f.type == "file" && Utils.likely_helm_chart?(f)
true
else
# This doesn't handle multi-resource files, but it shouldn't matter, since the first resource
# in a multi-resource file had better be a valid k8s resource
content = ::YAML.safe_load(T.must(f.content), aliases: true)
likely_kubernetes_resource?(content)
end
rescue ::Psych::Exception
false
end
end

sig { returns(T::Array[Dependabot::DependencyFile]) }
def incorrectly_encoded_yamlfiles
yamlfiles.reject { |f| f.content&.valid_encoding? }
end
end
end
end
Expand Down
Loading

0 comments on commit ffd081f

Please sign in to comment.