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

DevOps extension task new updater commands and options #1216

Merged
merged 15 commits into from
Jul 18, 2024
Next Next commit
Add new updater options
  • Loading branch information
Rhys Koedijk committed Jul 16, 2024
commit ee4e2f4b22124b084d1e94cf6a0874d37bf55219
47 changes: 46 additions & 1 deletion extension/task/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ async function run() {
dockerRunner.arg(["--rm"]); // remove after execution
dockerRunner.arg(["-i"]); // attach pseudo tty

// Set the job id, if one is provided
if (variables.jobId) {
dockerRunner.arg(["-e", `JOB_ID=${variables.jobId}`]);
}

// Set the github token, if one is provided
if (variables.githubAccessToken) {
dockerRunner.arg(["-e", `GITHUB_ACCESS_TOKEN=${variables.githubAccessToken}`]);
Expand Down Expand Up @@ -83,6 +88,11 @@ async function run() {
dockerRunner.arg(["-e", `DEPENDABOT_MILESTONE=${update.milestone}`]);
}

// Set the PR branch prefix
if (variables.branchNamePrefix) {
dockerRunner.arg(["-e", `DEPENDABOT_BRANCH_NAME_PREFIX=${variables.branchNamePrefix}`]);
}

// Set the PR branch separator
if (update.branchNameSeparator) {
dockerRunner.arg(["-e", `DEPENDABOT_BRANCH_NAME_SEPARATOR=${update.branchNameSeparator}`]);
Expand Down Expand Up @@ -111,6 +121,26 @@ async function run() {
dockerRunner.arg(["-e", `DEPENDABOT_IGNORE_CONDITIONS=${ignore}`]);
}

let prNamePrefixStyle = variables.prNamePrefixStyle;
if (prNamePrefixStyle) {
dockerRunner.arg(["-e", `DEPENDABOT_PR_NAME_PREFIX_STYLE=${prNamePrefixStyle}`]);
}

let prMessageHeader = variables.prMessageHeader;
if (prMessageHeader) {
dockerRunner.arg(["-e", `DEPENDABOT_MESSAGE_HEADER=${prMessageHeader}`]);
}

let prMessageFooter = variables.prMessageFooter;
if (prMessageFooter) {
dockerRunner.arg(["-e", `DEPENDABOT_MESSAGE_FOOTER=${prMessageFooter}`]);
}

let prCompatibilityScoreBadge = variables.prCompatibilityScoreBadge;
if (prCompatibilityScoreBadge) {
dockerRunner.arg(["-e", `DEPENDABOT_COMPATIBILITY_SCORE_BADGE=true`]);
}

// Set the commit message options
let commitMessage = update.commitMessage;
if (commitMessage) {
Expand Down Expand Up @@ -164,6 +194,11 @@ async function run() {
dockerRunner.arg(["-e", 'DEPENDABOT_SKIP_PULL_REQUESTS=true']);
}

// Set skip pull requests if true
if (variables.commentPullRequests === true) {
dockerRunner.arg(["-e", 'DEPENDABOT_COMMENT_PULL_REQUESTS=true']);
}

// Set abandon Unwanted pull requests if true
if (variables.abandonUnwantedPullRequests === true) {
dockerRunner.arg(["-e", 'DEPENDABOT_CLOSE_PULL_REQUESTS=true']);
Expand All @@ -176,6 +211,11 @@ async function run() {
dockerRunner.arg(["-e", `DEPENDABOT_SECURITY_ADVISORIES_FILE=${containerPath}`]);
}

let securityUpdatesOnly = variables.securityUpdatesOnly;
if (securityUpdatesOnly) {
dockerRunner.arg(["-e", `DEPENDABOT_SECURITY_UPDATES_ONLY=true`]);
}

/*
* Set env variables in the runner for Azure
*/
Expand Down Expand Up @@ -230,6 +270,11 @@ async function run() {
}
}

// Set debug
if (variables.debug === true) {
dockerRunner.arg(["-e", 'DEPENDABOT_DEBUG=true']);
}

// Add in extra environment variables
variables.extraEnvironmentVariables.forEach(extraEnvVar => {
dockerRunner.arg(["-e", extraEnvVar]);
Expand All @@ -247,7 +292,7 @@ async function run() {
dockerRunner.arg(dockerImage);

// set the script to be run
dockerRunner.arg('update_script');
dockerRunner.arg(variables.command);

// Now execute using docker
await dockerRunner.exec();
Expand Down
147 changes: 122 additions & 25 deletions extension/task/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,26 @@
"author": "Tingle Software",
"demands": ["docker"],
"version": {
"Major": 1,
"Minor": 5,
"Major": 2,
"Minor": 0,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mburumaxwell
I'm not sure what the implications for this are, but I figured it was probably best to separate the tasks by a major version since the options are quiet different.

My understanding is that users should be able to switch between v1 and v2 if for whatever reason v2 causes problems.

Let me know if you have any concerns about this or if you want me to dig in to it some more

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a different major version means we need to keep both in the task otherwise it fail for everyone. Keeping both means extension/taskv1 and extension/taskv2 with duplicate steps. This is what Microsoft does in their official tasks. My recommendation is to keep the current one and make modifications there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, makes sense. I have changed this to a minor version bump instead of a major.

"Patch": 0
},
"instanceNameFormat": "Dependabot",
"minimumAgentVersion": "2.105.0",
"groups": [
{
"name": "security_updates",
"displayName": "Security advisories, vulnerabilities, and updates.",
"displayName": "Security advisories and vulnerabilities",
"isExpanded": false
},
{
"name": "approval_completion",
"displayName": "Auto Approval and Auto Completion or PRs",
"name": "pull_requests",
"displayName": "Pull request options",
"isExpanded": false
},
{
"name": "devops",
"displayName": "Azure DevOps authentication",
"isExpanded": false
},
{
Expand All @@ -40,6 +45,28 @@
}
],
"inputs": [
{
"name": "command",
"type": "pickList",
"label": "Command",
"options": {
"update_script": "Update dependencies",
"update_script_vnext": "Update dependencies (vNext)",
"custom": "Custom"
},
"defaultValue": "update_script",
"required": true,
"helpMarkDown": "The Dependabot command to run. Select 'Custom' to use a command not listed here."
},
{
"name": "customCommand",
"type": "string",
"label": "Custom Command",
"defaultValue": "",
"required": false,
"helpMarkDown": "The custom command to run. This is only used when the command is set to 'Custom'.",
"visibleRule": "command=custom"
},
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let us make this just a boolean input to choose between updater_script and updater_vnext

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

"name": "useConfigFile",
"type": "boolean",
Expand All @@ -52,43 +79,92 @@
{
"name": "failOnException",
"type": "boolean",
"label": "Determines if the execution should fail when an exception occurs. Defaults to `true`",
"groupName": "advanced",
"label": "Fail task when an update exception occurs.",
"defaultValue": true,
"required": false,
"helpMarkDown": "When set to true, a failure in updating a single dependency will cause the container execution to fail thereby causing the task to fail. This is important when you want a single failure to prevent trying to update other dependencies."
"helpMarkDown": "When set to `true`, a failure in updating a single dependency will cause the container execution to fail thereby causing the task to fail. This is important when you want a single failure to prevent trying to update other dependencies."
},

{
"name": "skipPullRequests",
"type": "boolean",
"groupName": "advanced",
"label": "Whether to skip creation and updating of pull requests.",
"groupName": "pull_requests",
"label": "Skip creation and updating of pull requests.",
"defaultValue": false,
"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": "commentPullRequests",
"type": "boolean",
"groupName": "pull_requests",
"label": "Comment on abandoned pull requests with close reason.",
"defaultValue": false,
"required": false,
"helpMarkDown": "When set to `true` a comment will be added to abandoned pull requests explanating why it was closed. Defaults to `false`.",
"visibleRule": "command!=update_script"
},
{
"name": "abandonUnwantedPullRequests",
"type": "boolean",
"groupName": "advanced",
"label": "Whether to abandon unwanted pull requests.",
"groupName": "pull_requests",
"label": "Abandon unwanted pull requests.",
"defaultValue": false,
"required": false,
"helpMarkDown": "When set to `true` pull requests that are no longer needed are closed at the tail end of the execution. Defaults to `false`."
},

{
"name": "branchNamePrefix",
"type": "string",
"groupName": "pull_requests",
"label": "Git branch name prefix",
"defaultValue": "",
"required": false,
"helpMarkDown": "The prefix used for Git branch names. Defaults to 'dependabot'.",
"visibleRule": "command!=update_script"
},
{
"name": "prMessageHeader",
"type": "multiLine",
"groupName": "pull_requests",
"label": "Pull request description header",
"required": false,
"helpMarkDown": "Additional pull request description text to shown before the dependency change info.",
"visibleRule": "command!=update_script"
},
{
"name": "prMessageFooter",
"type": "multiLine",
"groupName": "pull_requests",
"label": "Pull request description footer",
"required": false,
"helpMarkDown": "Additional pull request description text to shown after the dependency change info. This text will not be truncated, even when the dependency change info exceeds the PR maximum description length.",
"visibleRule": "command!=update_script"
},
{
"name": "prCompatibilityScoreBadge",
"type": "boolean",
"groupName": "pull_requests",
"label": "Show update compatibility score badges in pull request description",
"defaultValue": false,
"required": false,
"helpMarkDown": "Determines if compatibility score badges are shown in the pull request description for single dependency updates (but not group updates). This feature uses public information from GitHub and enabling it does not send any private information about your repository to GitHub other than the dependency name and version number(s) required to calculate to the compatibility score.",
"visibleRule": "command!=update_script"
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe there is any value in exposing these settings. Maybe later we can if there is a need. It is better to keep tunable knobs as few as possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no worries, I've removed them for now. It might be a bit difficult to use the PR message header/footer variables in extraEnvironmentVariables since it is only a single line text input, but as you say we can maybe revisit this later.

{
"name": "setAutoComplete",
"type": "boolean",
"groupName": "approval_completion",
"label": "Determines if the pull requests that dependabot creates should have auto complete set.",
"groupName": "pull_requests",
"label": "Auto-complete pull requests when all policies pass",
"defaultValue": false,
"required": false,
"helpMarkDown": "When set to `true`, pull requests that pass all policies will be merged automatically. Defaults to `false`."
},
{
"name": "mergeStrategy",
"type": "pickList",
"groupName": "approval_completion",
"groupName": "pull_requests",
"label": "Merge Strategy",
"defaultValue": "squash",
"required": true,
Expand All @@ -104,25 +180,26 @@
{
"name": "autoCompleteIgnoreConfigIds",
"type": "string",
"groupName": "approval_completion",
"groupName": "pull_requests",
"label": "Semicolon delimited list of any policy configuration IDs which auto-complete should not wait for.",
"defaultValue": "",
"required": false,
"helpMarkDown": "A semicolon (`;`) delimited list of any policy configuration IDs which auto-complete should not wait for. Only applies to optional policies (isBlocking == false). Auto-complete always waits for required policies (isBlocking == true)."
"helpMarkDown": "A semicolon (`;`) delimited list of any policy configuration IDs which auto-complete should not wait for. Only applies to optional policies (isBlocking == false). Auto-complete always waits for required policies (isBlocking == true).",
"visibleRule": "setAutoComplete=true"
},
{
"name": "autoApprove",
"type": "boolean",
"groupName": "approval_completion",
"label": "Determines if the pull requests that dependabot creates should be automatically approved.",
"groupName": "pull_requests",
"label": "Auto-approve pull requests",
"defaultValue": false,
"required": false,
"helpMarkDown": "When set to `true`, pull requests will automatically be approved by the specified user. Defaults to `false`."
},
{
"name": "autoApproveUserToken",
"type": "string",
"groupName": "approval_completion",
"groupName": "pull_requests",
"label": "A personal access token of the user that should approve the PR.",
"defaultValue": "",
"required": false,
Expand All @@ -149,6 +226,16 @@
"helpMarkDown": "The raw Personal Access Token for accessing GitHub repositories. Use this in place of `gitHubConnection` such as when it is not possible to create a service connection."
},

{
"name": "securityUpdatesOnly",
"type": "boolean",
"groupName": "security_updates",
"label": "Perform security updates only.",
"defaultValue": "false",
"required": false,
"helpMarkDown": "If `true`, only security updates will be processed. Defaults to `false`.",
"visibleRule": "command!=update_script"
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an existing way to get this condition. Let us keep it so that we are very close to the official implementation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I have changed this to follow the official implementation

{
"name": "securityAdvisoriesFile",
"type": "string",
Expand All @@ -161,15 +248,15 @@
{
"name": "azureDevOpsServiceConnection",
"type": "connectedService:Externaltfs",
"groupName": "advanced",
"groupName": "devops",
"label": "Azure DevOps Service Connection to use.",
"required": false,
"helpMarkDown": "Specify a service connection to use, if you want to use a different service principal than the default to create your PRs."
},
{
"name": "azureDevOpsAccessToken",
"type": "string",
"groupName": "advanced",
"groupName": "devops",
"label": "Azure DevOps Personal Access Token.",
"required": false,
"helpMarkDown": "The Personal Access Token for accessing Azure DevOps repositories. 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. Use this in place of `azureDevOpsServiceConnection` such as when it is not possible to create a service connection."
Expand All @@ -195,17 +282,18 @@
"name": "updaterOptions",
"type": "string",
"groupName": "advanced",
"label": "Comma separated list of updater options.",
"label": "Dependabot experiments (updater options).",
"required": false,
"helpMarkDown": "Set a list of updater options in CSV format. Available options depend on the ecosystem. Example: `goprivate=true,kubernetes_updates=true`."
"helpMarkDown": "Set a list of Dependabot experiments (updater options) in CSV format. Available options depend on the ecosystem. Example: `goprivate=true,kubernetes_updates=true`."
},
{
"name": "excludeRequirementsToUnlock",
"type": "string",
"groupName": "advanced",
"label": "Space-separated list of dependency updates requirements to be excluded.",
"required": false,
"helpMarkDown": "Exclude certain dependency updates requirements. See list of allowed values [here](https://github.com/dependabot/dependabot-core/issues/600#issuecomment-407808103). Useful if you have lots of dependencies and the update script too slow. The values provided are space-separated. Example: `own all` to only use the `none` version requirement."
"helpMarkDown": "Exclude certain dependency updates requirements. See list of allowed values [here](https://github.com/dependabot/dependabot-core/issues/600#issuecomment-407808103). Useful if you have lots of dependencies and the update script too slow. The values provided are space-separated. Example: `own all` to only use the `none` version requirement.",
"visibleRule": "command!=update_script_vnext"
},
{
"name": "dockerImageTag",
Expand All @@ -232,6 +320,15 @@
"defaultValue": "false",
"required": false,
"helpMarkDown": "Ensure that the host ssh socket is forwarded to the container to authenticate with ssh"
},
{
"name": "debug",
"type": "boolean",
"groupName": "advanced",
"label": "Show debug log messages",
"defaultValue": "false",
"required": false,
"helpMarkDown": "Determines if verbose log messages are logged. Useful for diagnosing issues. Defaults to `false`."
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea, done.

],
"dataSourceBindings": [],
Expand Down
Loading