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

Make abandoning PRs optional but enabled by default #448

Merged
merged 1 commit into from
Dec 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions extension/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ This task makes use of a docker image, which may take time to install. Subsequen
|autoApprove|**_Optional_**. Determines if the pull requests that dependabot creates should be automatically completed. When set to `true`, pull requests will be approved automatically. To use a different user for approval, supply `autoApproveUserToken` input. Defaults to `false`.|
|autoApproveUserToken|**_Optional_**. A personal access token for the user to automatically approve the created PR.|
|skipPullRequests|**_Optional_**. Determines whether to skip creation and updating of pull requests. When set to `true` the logic to update the dependencies is executed but the actual Pull Requests are not created/updated. This is useful for debugging. Defaults to `false`.|
|abandonUnwantedPullRequests|**_Optional_**. Determines whether to abandon unwanted pull requests. Defaults to `false`.|
|gitHubConnection|**_Optional_**. The GitHub service connection for authenticating requests against GitHub repositories. This is useful to avoid rate limiting errors. The token must include permissions to read public repositories. See the [GitHub docs](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token) for more on Personal Access Tokens and [Azure DevOps docs](https://docs.microsoft.com/en-us/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml#sep-github) for the GitHub service connection.|
|gitHubAccessToken|**_Optional_**. The raw GitHub PAT for authenticating requests against GitHub repositories. Use this in place of `gitHubConnection` such as when it is not possible to create a service connection.|
|azureDevOpsAccessToken|**_Optional_**. The Personal Access Token for accessing Azure DevOps. Supply a value here to avoid using permissions for the Build Service either because you cannot change its permissions or because you prefer that the Pull Requests be done by a different user. When not provided, the current authentication scope is used. In either case, be use the following permissions are granted: <br/>-&nbsp;Code (Full)<br/>-&nbsp;Pull Requests Threads (Read & Write).<br/>See the [documentation](https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=preview-page#create-a-pat) to know more about creating a Personal Access Token|
Expand Down
5 changes: 5 additions & 0 deletions extension/task/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ async function run() {
dockerRunner.arg(["-e", 'DEPENDABOT_SKIP_PULL_REQUESTS=true']);
}

// Set abandon Unwanted pull requests if true
if (variables.abandonUnwantedPullRequests === true) {
dockerRunner.arg(["-e", 'DEPENDABOT_CLOSE_PULL_REQUESTS=true']);
}

// Set the security advisories
if (variables.securityAdvisoriesFile) {
const containerPath = "/mnt/security_advisories.json"
Expand Down
9 changes: 9 additions & 0 deletions extension/task/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,15 @@
"required": false,
"helpMarkDown": "When set to `true` the logic to update the dependencies is executed but the actual Pull Requests are not created/updated. Defaults to `false`."
},
{
"name": "abandonUnwantedPullRequests",
"type": "boolean",
"groupName": "advanced",
"label": "Whether to abandon unwanted pull requests.",
"defaultValue": true,
"required": false,
"helpMarkDown": "When set to `true` the logic to update the dependencies is executed but the actual Pull Requests are not created/updated. Defaults to `false`."
},

{
"name": "setAutoComplete",
Expand Down
4 changes: 4 additions & 0 deletions extension/task/utils/getSharedVariables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ export interface ISharedVariables {
extraCredentials: string;
/** Determines whether to skip creating/updating pull requests */
skipPullRequests: boolean;
/** Determines whether to abandon unwanted pull requests */
abandonUnwantedPullRequests: boolean;
/** List of extra environment variables */
extraEnvironmentVariables: string[];
/** Flag used to forward the host ssh socket */
Expand Down Expand Up @@ -139,6 +141,7 @@ export default function getSharedVariables(): ISharedVariables {
);
let extraCredentials = tl.getVariable("DEPENDABOT_EXTRA_CREDENTIALS");
let skipPullRequests: boolean = tl.getBoolInput("skipPullRequests", false);
let abandonUnwantedPullRequests: boolean = tl.getBoolInput("abandonUnwantedPullRequests", true);
let extraEnvironmentVariables = tl.getDelimitedInput(
"extraEnvironmentVariables",
";",
Expand Down Expand Up @@ -193,6 +196,7 @@ export default function getSharedVariables(): ISharedVariables {
securityAdvisoriesFile,
extraCredentials,
skipPullRequests,
abandonUnwantedPullRequests,
extraEnvironmentVariables,
forwardHostSshSocket,

Expand Down
101 changes: 52 additions & 49 deletions script/update-script.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
},
fail_on_exception: ENV['DEPENDABOT_FAIL_ON_EXCEPTION'] == "true", # Stop the job if an exception occurs
skip_pull_requests: ENV['DEPENDABOT_SKIP_PULL_REQUESTS'] == "true", # Skip creating/updating Pull Requests
close_unwanted: ENV['DEPENDABOT_CLOSE_PULL_REQUESTS'] == "true", # Close unwanted Pull Requests

# See description of requirements here:
# https://github.com/dependabot/dependabot-core/issues/600#issuecomment-407808103
Expand Down Expand Up @@ -759,60 +760,62 @@ def peer_dependency_should_update_instead?(dependency_name, updated_deps, files,
end

# look for pull requests that are no longer needed to be abandoned
puts "Looking for pull requests that are no longer needed."
active_pull_requests = azure_client.pull_requests_active(user_id, default_branch_name)
active_pull_requests.each do |pr|
pr_id = pr["pullRequestId"]
title = pr["title"]
source_ref_name = pr["sourceRefName"]
if $options[:close_unwanted]
puts "Looking for pull requests that are no longer needed."
active_pull_requests = azure_client.pull_requests_active(user_id, default_branch_name)
active_pull_requests.each do |pr|
pr_id = pr["pullRequestId"]
title = pr["title"]
source_ref_name = pr["sourceRefName"]

begin
keep = false
dependencies.select(&:top_level?).each do |dep|
# Sometimes, the dep.version might be null such as in npm
# when the package.lock.json is not checked into source.
next unless dep.version

# CHECKING BY VERSION DOESN'T SEEM TO WORK. THE CODE IS HERE FOR REFERENCE

# Check if the version has since been ignored, it so we do not keep
requirement_class = Dependabot::Utils.requirement_class_for_package_manager(dep.package_manager)
ignore_reqs = ignored_versions_for(dep)
.flat_map { |req| requirement_class.requirements_array(req) }
if ignore_reqs.any? { |req| req.satisfied_by?(dep.version) }
puts "Update for #{dep.name} #{dep.version} is no longer required."
next
end

begin
keep = false
dependencies.select(&:top_level?).each do |dep|
# Sometimes, the dep.version might be null such as in npm
# when the package.lock.json is not checked into source.
next unless dep.version

# CHECKING BY VERSION DOESN'T SEEM TO WORK. THE CODE IS HERE FOR REFERENCE

# Check if the version has since been ignored, it so we do not keep
requirement_class = Dependabot::Utils.requirement_class_for_package_manager(dep.package_manager)
ignore_reqs = ignored_versions_for(dep)
.flat_map { |req| requirement_class.requirements_array(req) }
if ignore_reqs.any? { |req| req.satisfied_by?(dep.version) }
puts "Update for #{dep.name} #{dep.version} is no longer required."
next
# Ensure the title contains the current dependency name and version.
#
# Samples:
# Bump Tingle.Extensions.Logging.LogAnalytics from 3.4.2-ci0005 to 3.4.2-ci0006
# chore(deps): bump dotenv from 9.0.1 to 9.0.2 in /server
#
# display_name is used instead of name because some titles do not have the full dependency name.
# For instance 'org.junit.jupiter:junit-jupiter' will only read 'junit-jupiter' in the title.
keep = title.include?("#{dep.display_name} from #{dep.version} to ")

# Break if the PR should be kept
break if keep
end

# Ensure the title contains the current dependency name and version.
#
# Samples:
# Bump Tingle.Extensions.Logging.LogAnalytics from 3.4.2-ci0005 to 3.4.2-ci0006
# chore(deps): bump dotenv from 9.0.1 to 9.0.2 in /server
#
# display_name is used instead of name because some titles do not have the full dependency name.
# For instance 'org.junit.jupiter:junit-jupiter' will only read 'junit-jupiter' in the title.
keep = title.include?("#{dep.display_name} from #{dep.version} to ")

# Break if the PR should be kept
break if keep
end

# Abandon the PR unless we should keep it
unless keep
if $options[:skip_pull_requests]
puts "Skipping abandoning PR ##{pr_id} (#{title})"
else
puts "Abandoning PR ##{pr_id} (#{title}) as it is no longer needed."
azure_client.branch_delete(source_ref_name)
azure_client.pull_request_abandon(pr_id)
# Abandon the PR unless we should keep it
unless keep
if $options[:skip_pull_requests]
puts "Skipping abandoning PR ##{pr_id} (#{title})"
else
puts "Abandoning PR ##{pr_id} (#{title}) as it is no longer needed."
azure_client.branch_delete(source_ref_name)
azure_client.pull_request_abandon(pr_id)
end
end
end

rescue StandardError => e
raise e if $options[:fail_on_exception]
puts "Error checking whether to abandon (or abandoning) PR ##{pr_id} (continuing)"
puts e.full_message
rescue StandardError => e
raise e if $options[:fail_on_exception]
puts "Error checking whether to abandon (or abandoning) PR ##{pr_id} (continuing)"
puts e.full_message
end
end
end

Expand Down