From c28cb3dd9ed921e569d66737951846ecd396eb38 Mon Sep 17 00:00:00 2001 From: Nils Andresen Date: Mon, 26 Oct 2020 20:53:52 +0100 Subject: [PATCH] initial idea --- .gitattributes | 11 ++++ LICENSE.txt | 21 ++++++ README.md | 113 ++++++++++++++++++++++++++++++++ action.yml | 33 ++++++++++ src/Dockerfile | 30 +++++++++ src/app/Gemfile | 7 ++ src/app/dependabot.rb | 148 ++++++++++++++++++++++++++++++++++++++++++ src/run-action.sh | 5 ++ 8 files changed, 368 insertions(+) create mode 100644 .gitattributes create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 action.yml create mode 100644 src/Dockerfile create mode 100644 src/app/Gemfile create mode 100644 src/app/dependabot.rb create mode 100644 src/run-action.sh diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..4b12527 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +* text=auto + +# Set line endings to LF, even on Windows. Otherwise, execution within Docker fails. +# See https://help.github.com/articles/dealing-with-line-endings/ +*.sh text eol=lf +*.rb text eol=lf + +# Exclude files from exporting + +.gitattributes export-ignore +.gitignore export-ignore \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..2d5be7c --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Nils Andresen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..a377f52 --- /dev/null +++ b/README.md @@ -0,0 +1,113 @@ +# dependabot-cake-action + +A github action for running dependabot on repositories using cake-build. + +## Table of Contents + +- [Background](#background) +- [Install](#install) +- [Usage](#usage) +- [Limitations](#limitations) +- [Idea / Attribution](#idea--attribution) +- [Full Example](#full-example) +- [Running Locally](#running-locally) +- [Maintainers](#maintainers) +- [Contributing](#contributing) +- [License](#license) + +## Background + +This action provides the features, as developed for https://github.com/dependabot/dependabot-core/pull/1848 (a PR for https://github.com/dependabot/dependabot-core/issues/733): **To have dependabot check cake-references**. + +Currently dependabot does not support this and sadly merging https://github.com/dependabot/dependabot-core/pull/1848 might take some time. In the meantime it is possibe to use the code provided in the PR to do the checking "manually". + +This action provides the means to do so. + +## Install + +Use the action in your workflow yaml by adding a step with `uses: nils-org/dependabot-cake-action@v1`. + +## Usage + +```yml +- name: check/update cake references + uses: nils-org/dependabot-cake-action@v1 + with: + # Where to look for cake files to check for dependency upgrades. + # The directory is relative to the repository's root. + # Multiple paths can be provided by splitting them with a new line. + # Example: + # directory: | + # /path/to/first/module + # /path/to/second/module + # Default: "/" + directory: "" + + # Branch to create pull requests against. + # By default your repository's default branch is used. + target_branch: "" + + # Auth token used to push the changes back to github and create the pull request with. + # [Learn more about creating and using encrypted secrets](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets) + # default: ${{ github.token }} + token: "" +``` + +## Limitations + +This not a read dependabot, so there so "commands" to give (like `@dependabot rebase` and such). If you need to rebase the PR, you'll have to do that manually. + +TODOs: +* Check what happens when a PR is not merged and closed. Will it simply be re-created every run? +* How to "ignore" dependencies? + +## Idea / Attribution + +Most of this was shamelessly copied from https://github.com/patrickjahns/dependabot-terraform-action/ + +## Full Example +Save the following content in you're repo under `.github/workflows/dependabot-cake.yml` +```yml +name: dependabot-cake +on: + workflow_dispatch: + schedule: + # run everyday at 6 + - cron: '0 6 * * *' + +jobs: + dependabot-cake: + runs-on: ubuntu-latest # linux, because this is a docker-action + steps: + - name: check/update cake dependencies + uses: nils-org/dependabot-cake-action@v1 +``` + +## Running Locally +It is also possible to run this action locally: + +* Clone this repo +* build the docker image + + `cd src && docker build -t dependabot-cake:latest .` +* run the container and give the needed environment-vars + + `docker run -e GITHUB_REPOSITORY=nils-a/Cake.7zip -e INPUT_TARGET_BRANCH=develop -e INPUT_TOKEN=your-github-api-token dependabot-cake` + + +## Maintainers + +[Nils Andresen @nils-a](https://github.com/nils-a). + +## Contributing +We accept Pull Requests. + +Small note: If editing the Readme, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification. + +### Contributors + +* Nils Andresen + +## License + +[MIT License © Nils Andresen][LICENSE.txt] \ No newline at end of file diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..0d8f744 --- /dev/null +++ b/action.yml @@ -0,0 +1,33 @@ +name: 'cake-dependabot' +description: 'Dependency updater for cake build files' +author: 'nils-a' +inputs: + directory: + description: > + Where to look for cake files to check for dependency upgrades. + The directory is relative to the repository's root. + Multiple paths can be provided by splitting them with a new line. + Example: + directory: | + /path/to/first/module + /path/to/second/module + default: "/" + required: false + target_branch: + description: > + Branch to create pull requests against. + By default your repository's default branch is used. + required: false + token: + description: > + Auth token used to push the changes back to github and create the pull request with. + [Learn more about creating and using encrypted secrets](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets) + default: ${{ github.token }} + required: false + +runs: + using: 'docker' + image: 'docker://nilsa/dependabot-cake' +branding: + icon: 'package' + color: 'orange' \ No newline at end of file diff --git a/src/Dockerfile b/src/Dockerfile new file mode 100644 index 0000000..5f05870 --- /dev/null +++ b/src/Dockerfile @@ -0,0 +1,30 @@ +FROM ruby:2.6.6-slim + +LABEL "maintainer"="Nils Andresen " \ + "repository"="https://github.com/nils-org/dependabot-cake-action" \ + "homepage"="https://github.com/nils-org/dependabot-cake-action" \ + "com.github.actions.name"="dependabot-cake-action" \ + "com.github.actions.description"="Run dependabot for cake as github action" \ + "com.github.actions.icon"="check-circle" \ + "com.github.actions.color"="package" + +WORKDIR /usr/src/app +#ENV DEPENDABOT_NATIVE_HELPERS_PATH="/usr/src/app/native-helpers" + +COPY ./app /usr/src/app +COPY ./run-action.sh /usr/local/bin/run-action.sh + +# install needed tools +RUN apt-get update && \ + apt-get install -y build-essential git wget + +# install rb dependencies +RUN bundle install + +# remove runtime-unnedded tools & cleanup +RUN apt-get remove -y build-essential && \ + apt-get autoremove -y && \ + apt-get clean && \ + rm -rf /tmp/* + +CMD ["run-action.sh"] \ No newline at end of file diff --git a/src/app/Gemfile b/src/app/Gemfile new file mode 100644 index 0000000..1fe59b3 --- /dev/null +++ b/src/app/Gemfile @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +ruby "2.6.6" +source "https://rubygems.org" + +gem "dependabot-omnibus", "~> 0.123.0" +gem 'dependabot-cake', git: 'https://github.com/pharos/dependabot-core', branch: "add-support-for-cake" diff --git a/src/app/dependabot.rb b/src/app/dependabot.rb new file mode 100644 index 0000000..198c813 --- /dev/null +++ b/src/app/dependabot.rb @@ -0,0 +1,148 @@ +#!/usr/bin/env ruby + +require "dependabot/file_fetchers" +require "dependabot/file_parsers" +require "dependabot/update_checkers" +require "dependabot/file_updaters" +require "dependabot/pull_request_creator" +require "dependabot/omnibus" + + +# Utilize the github env variable per default +repo_name = ENV["GITHUB_REPOSITORY"] +if !repo_name || repo_name.empty? + print "GITHUB_REPOSITORY needs to be set" + exit(1) +end + +# Directory where the base dependency files are. +directory = ENV["INPUT_DIRECTORY"] || "/" +directory = directory.gsub(/\\n/, "\n") +if directory&.empty? + print "The directory needs to be set" + exit(1) +end + +# Define the target branch +target_branch = ENV["INPUT_TARGET_BRANCH"] +if target_branch && target_branch.empty? + target_branch=nil +end + +# Token to be used for fetching repository files / creating pull requests +repo_token = ENV["INPUT_TOKEN"] +if !repo_token || repo_token.empty? + print "A github token needs to be provided" + exit(1) +end + +credentials_repository = [ + { + "type" => "git_source", + "host" => "github.com", + "username" => "x-access-token", + "password" => repo_token + } +] + +def update(source, credentials_repository) + + # Hardcode the package manager to cake + package_manager = "cake" + + ############################## + # Fetch the dependency files # + ############################## + fetcher = Dependabot::FileFetchers.for_package_manager(package_manager).new( + source: source, + credentials: credentials_repository, + ) + + files = fetcher.files + commit = fetcher.commit + + ############################## + # Parse the dependency files # + ############################## + puts " - Parsing dependencies information" + parser = Dependabot::FileParsers.for_package_manager(package_manager).new( + dependency_files: files, + source: source, + credentials: credentials_repository, + ) + + dependencies = parser.parse + + dependencies.select(&:top_level?).each do |dep| + ######################################### + # Get update details for the dependency # + ######################################### + checker = Dependabot::UpdateCheckers.for_package_manager(package_manager).new( + dependency: dep, + dependency_files: files, + credentials: credentials_repository, + ) + + next if checker.up_to_date? + + requirements_to_unlock = + if !checker.requirements_unlocked_or_can_be? + if checker.can_update?(requirements_to_unlock: :none) then :none + else :update_not_possible + end + elsif checker.can_update?(requirements_to_unlock: :own) then :own + elsif checker.can_update?(requirements_to_unlock: :all) then :all + else :update_not_possible + end + + next if requirements_to_unlock == :update_not_possible + + updated_deps = checker.updated_dependencies( + requirements_to_unlock: requirements_to_unlock + ) + + ##################################### + # Generate updated dependency files # + ##################################### + print " - Updating #{dep.name} (from #{dep.version})…" + updater = Dependabot::FileUpdaters.for_package_manager(package_manager).new( + dependencies: updated_deps, + dependency_files: files, + credentials: credentials_repository, + ) + + updated_files = updater.updated_dependency_files + + ######################################## + # Create a pull request for the update # + ######################################## + pr_creator = Dependabot::PullRequestCreator.new( + source: source, + base_commit: commit, + dependencies: updated_deps, + files: updated_files, + credentials: credentials_repository, + label_language: false, + ) + pull_request = pr_creator.create + puts " - submitted" + + next unless pull_request + + end +end + +puts " - Fetching dependency files for #{repo_name}" +directory.split("\n").each do |dir| + puts " - Checking #{dir} ..." + + source = Dependabot::Source.new( + provider: "github", + repo: repo_name, + directory: dir.strip, + branch: target_branch, + ) + update source, credentials_repository +end + +puts " - Done" \ No newline at end of file diff --git a/src/run-action.sh b/src/run-action.sh new file mode 100644 index 0000000..264dc66 --- /dev/null +++ b/src/run-action.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +set -e +pushd /usr/src/app > /dev/null +bundle exec ./dependabot.rb +popd \ No newline at end of file