From 09ec40a29c8266be27806ec91f385eef281be0fa Mon Sep 17 00:00:00 2001 From: travis plunk Date: Thu, 28 Apr 2022 11:40:20 -0700 Subject: [PATCH 01/11] Add backport action --- .github/workflows/backport.yml | 61 ++++++++++++ tools/actions/backport/action.yml | 20 ++++ tools/actions/backport/index.js | 157 ++++++++++++++++++++++++++++++ 3 files changed, 238 insertions(+) create mode 100644 .github/workflows/backport.yml create mode 100644 tools/actions/backport/action.yml create mode 100644 tools/actions/backport/index.js diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml new file mode 100644 index 00000000000..830dc23aee4 --- /dev/null +++ b/.github/workflows/backport.yml @@ -0,0 +1,61 @@ +name: Backport PR to branch +on: + issue_comment: + types: [created] + +permissions: + contents: write + issues: write + pull-requests: write + +jobs: + backport: + if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '/backport to') + runs-on: ubuntu-20.04 + steps: + - name: Extract backport target branch + uses: actions/github-script@v3 + id: target-branch-extractor + with: + result-encoding: string + script: | + if (context.eventName !== "issue_comment") throw "Error: This action only works on issue_comment events."; + + // extract the target branch name from the trigger phrase containing these characters: a-z, A-Z, digits, forward slash, dot, hyphen, underscore + const regex = /^\/backport to ([a-zA-Z\d\/\.\-\_]+)/; + target_branch = regex.exec(context.payload.comment.body); + if (target_branch == null) throw "Error: No backport branch found in the trigger phrase."; + + return target_branch[1]; + - name: Post backport started comment to pull request + uses: actions/github-script@v3 + with: + script: | + const backport_start_body = `Started backporting to ${{ steps.target-branch-extractor.outputs.result }}: https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${process.env.GITHUB_RUN_ID}`; + await github.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: backport_start_body + }); + - name: Checkout repo + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Run backport + uses: ./tools/actions/backport + with: + target_branch: ${{ steps.target-branch-extractor.outputs.result }} + auth_token: ${{ secrets.GITHUB_TOKEN }} + pr_description_template: | + Backport of #%source_pr_number% to %target_branch% + + /cc %cc_users% + + ## Customer Impact + + ## Testing + + ## Risk + + IMPORTANT: If this change touches code that ships in a NuGet package, please make certain that you have added any necessary [package authoring](https://github.com/dotnet/runtime/blob/main/docs/project/library-servicing.md) and gotten it explicitly reviewed. diff --git a/tools/actions/backport/action.yml b/tools/actions/backport/action.yml new file mode 100644 index 00000000000..e596f1dd586 --- /dev/null +++ b/tools/actions/backport/action.yml @@ -0,0 +1,20 @@ +name: 'PR Backporter' +description: 'Backports a pull request to a branch using the "/backport to " comment' +inputs: + target_branch: + description: 'Backport target branch.' + auth_token: + description: 'The token used to authenticate to GitHub.' + pr_title_template: + description: 'The template used for the PR title. Special placeholder tokens that will be replaced with a value: %target_branch%, %source_pr_title%, %source_pr_number%, %cc_users%.' + default: '[%target_branch%] %source_pr_title%' + pr_description_template: + description: 'The template used for the PR description. Special placeholder tokens that will be replaced with a value: %target_branch%, %source_pr_title%, %source_pr_number%, %cc_users%.' + default: | + Backport of #%source_pr_number% to %target_branch% + + /cc %cc_users% + +runs: + using: 'node12' + main: 'index.js' diff --git a/tools/actions/backport/index.js b/tools/actions/backport/index.js new file mode 100644 index 00000000000..88d348f167d --- /dev/null +++ b/tools/actions/backport/index.js @@ -0,0 +1,157 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// from https://github.com/dotnet/runtime/blob/main/eng/actions/backport/index.js + +function BackportException(message, postToGitHub = true) { + this.message = message; + this.postToGitHub = postToGitHub; + } + + async function run() { + const util = require("util"); + const jsExec = util.promisify(require("child_process").exec); + + console.log("Installing npm dependencies"); + const { stdout, stderr } = await jsExec("npm install @actions/core @actions/github @actions/exec"); + console.log("npm-install stderr:\n\n" + stderr); + console.log("npm-install stdout:\n\n" + stdout); + console.log("Finished installing npm dependencies"); + + const core = require("@actions/core"); + const github = require("@actions/github"); + const exec = require("@actions/exec"); + + const repo_owner = github.context.payload.repository.owner.login; + const repo_name = github.context.payload.repository.name; + const pr_number = github.context.payload.issue.number; + const comment_user = github.context.payload.comment.user.login; + + let octokit = github.getOctokit(core.getInput("auth_token", { required: true })); + let target_branch = core.getInput("target_branch", { required: true }); + + try { + // verify the comment user is a repo collaborator + try { + await octokit.rest.repos.checkCollaborator({ + owner: repo_owner, + repo: repo_name, + username: comment_user + }); + console.log(`Verified ${comment_user} is a repo collaborator.`); + } catch (error) { + console.log(error); + throw new BackportException(`Error: @${comment_user} is not a repo collaborator, backporting is not allowed. If you're a collaborator please make sure your Microsoft team membership visibility is set to Public on https://github.com/orgs/microsoft/people?query=${comment_user}`); + } + + try { await exec.exec(`git ls-remote --exit-code --heads origin ${target_branch}`) } catch { throw new BackportException(`Error: The specified backport target branch ${target_branch} wasn't found in the repo.`); } + console.log(`Backport target branch: ${target_branch}`); + + console.log("Applying backport patch"); + + await exec.exec(`git checkout ${target_branch}`); + await exec.exec(`git clean -xdff`); + + // configure git + await exec.exec(`git config user.name "github-actions"`); + await exec.exec(`git config user.email "github-actions@github.com"`); + + // create temporary backport branch + const temp_branch = `backport/pr-${pr_number}-to-${target_branch}`; + await exec.exec(`git checkout -b ${temp_branch}`); + + // skip opening PR if the branch already exists on the origin remote since that means it was opened + // by an earlier backport and force pushing to the branch updates the existing PR + let should_open_pull_request = true; + try { + await exec.exec(`git ls-remote --exit-code --heads origin ${temp_branch}`); + should_open_pull_request = false; + } catch { } + + // download and apply patch + await exec.exec(`curl -sSL "${github.context.payload.issue.pull_request.patch_url}" --output changes.patch`); + + const git_am_command = "git am --3way --ignore-whitespace --keep-non-patch changes.patch"; + let git_am_output = `$ ${git_am_command}\n\n`; + let git_am_failed = false; + try { + await exec.exec(git_am_command, [], { + listeners: { + stdout: function stdout(data) { git_am_output += data; }, + stderr: function stderr(data) { git_am_output += data; } + } + }); + } catch (error) { + git_am_output += error; + git_am_failed = true; + } + + if (git_am_failed) { + const git_am_failed_body = `@${github.context.payload.comment.user.login} backporting to ${target_branch} failed, the patch most likely resulted in conflicts:\n\n\`\`\`shell\n${git_am_output}\n\`\`\`\n\nPlease backport manually!`; + await octokit.rest.issues.createComment({ + owner: repo_owner, + repo: repo_name, + issue_number: pr_number, + body: git_am_failed_body + }); + throw new BackportException("Error: git am failed, most likely due to a merge conflict.", false); + } + else { + // push the temp branch to the repository + await exec.exec(`git push --force --set-upstream origin HEAD:${temp_branch}`); + } + + if (!should_open_pull_request) { + console.log("Backport temp branch already exists, skipping opening a PR."); + return; + } + + // prepate the GitHub PR details + let backport_pr_title = core.getInput("pr_title_template"); + let backport_pr_description = core.getInput("pr_description_template"); + + // get users to cc (append PR author if different from user who issued the backport command) + let cc_users = `@${comment_user}`; + if (comment_user != github.context.payload.issue.user.login) cc_users += ` @${github.context.payload.issue.user.login}`; + + // replace the special placeholder tokens with values + backport_pr_title = backport_pr_title + .replace(/%target_branch%/g, target_branch) + .replace(/%source_pr_title%/g, github.context.payload.issue.title) + .replace(/%source_pr_number%/g, github.context.payload.issue.number) + .replace(/%cc_users%/g, cc_users); + + backport_pr_description = backport_pr_description + .replace(/%target_branch%/g, target_branch) + .replace(/%source_pr_title%/g, github.context.payload.issue.title) + .replace(/%source_pr_number%/g, github.context.payload.issue.number) + .replace(/%cc_users%/g, cc_users); + + // open the GitHub PR + await octokit.rest.pulls.create({ + owner: repo_owner, + repo: repo_name, + title: backport_pr_title, + body: backport_pr_description, + head: temp_branch, + base: target_branch + }); + + console.log("Successfully opened the GitHub PR."); + } catch (error) { + + core.setFailed(error); + + if (error.postToGitHub === undefined || error.postToGitHub == true) { + // post failure to GitHub comment + const unknown_error_body = `@${comment_user} an error occurred while backporting to ${target_branch}, please check the run log for details!\n\n${error.message}`; + await octokit.rest.issues.createComment({ + owner: repo_owner, + repo: repo_name, + issue_number: pr_number, + body: unknown_error_body + }); + } + } + } + + run(); From c25b22addded9eb0dcc067306b27e3785304f47a Mon Sep 17 00:00:00 2001 From: Travis Plunk Date: Thu, 28 Apr 2022 11:58:48 -0700 Subject: [PATCH 02/11] Apply suggestions from code review --- .github/workflows/backport.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index 830dc23aee4..5db15fad8c9 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -55,7 +55,6 @@ jobs: ## Customer Impact ## Testing - +- [ ] For any change that affects the release process, please work with a maintainer to come up with a plan to test this. ## Risk - IMPORTANT: If this change touches code that ships in a NuGet package, please make certain that you have added any necessary [package authoring](https://github.com/dotnet/runtime/blob/main/docs/project/library-servicing.md) and gotten it explicitly reviewed. From 6c4fcfded0330142b762e9f6d595ea861c3ce422 Mon Sep 17 00:00:00 2001 From: Travis Plunk Date: Thu, 28 Apr 2022 11:59:38 -0700 Subject: [PATCH 03/11] Update .github/workflows/backport.yml --- .github/workflows/backport.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index 5db15fad8c9..fc9a44c30f5 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -55,6 +55,8 @@ jobs: ## Customer Impact ## Testing -- [ ] For any change that affects the release process, please work with a maintainer to come up with a plan to test this. + + - [ ] For any change that affects the release process, please work with a maintainer to come up with a plan to test this. + ## Risk From e09a8b34ffd29b1d4d15016be8a2a4159df63ddc Mon Sep 17 00:00:00 2001 From: travis plunk Date: Thu, 28 Apr 2022 12:01:52 -0700 Subject: [PATCH 04/11] Fix codefactor issues --- .github/workflows/backport.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index fc9a44c30f5..2a32b62d1d5 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -55,8 +55,7 @@ jobs: ## Customer Impact ## Testing - + - [ ] For any change that affects the release process, please work with a maintainer to come up with a plan to test this. - - ## Risk + ## Risk From 87c38ae4a9dc8c15245822a2f922a10dc932c040 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 Apr 2022 18:34:31 +0000 Subject: [PATCH 05/11] Bump PSReadLine from 2.1.0 to 2.2.3 in /src/Modules Bumps PSReadLine from 2.1.0 to 2.2.3. --- updated-dependencies: - dependency-name: PSReadLine dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- src/Modules/PSGalleryModules.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Modules/PSGalleryModules.csproj b/src/Modules/PSGalleryModules.csproj index 1bbb056765f..9189f782b40 100644 --- a/src/Modules/PSGalleryModules.csproj +++ b/src/Modules/PSGalleryModules.csproj @@ -14,7 +14,7 @@ - + From 9dc8b64f91bf6d5adac57817ca933a0c155099ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 Apr 2022 17:37:36 -0700 Subject: [PATCH 06/11] Bump PackageManagement from 1.4.7 to 1.4.7.1 in /src/Modules (#177) Bumps PackageManagement from 1.4.7 to 1.4.7.1. --- updated-dependencies: - dependency-name: PackageManagement dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/Modules/PSGalleryModules.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Modules/PSGalleryModules.csproj b/src/Modules/PSGalleryModules.csproj index 9189f782b40..638184d15f0 100644 --- a/src/Modules/PSGalleryModules.csproj +++ b/src/Modules/PSGalleryModules.csproj @@ -12,7 +12,7 @@ - + From d85c2ad0d83be3907d3fb6c531fe75e4446b6e57 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 May 2022 11:56:06 -0700 Subject: [PATCH 07/11] Bump StyleCop.Analyzers from 1.2.0-beta.406 to 1.2.0-beta.435 (#182) Bumps [StyleCop.Analyzers](https://github.com/DotNetAnalyzers/StyleCopAnalyzers) from 1.2.0-beta.406 to 1.2.0-beta.435. - [Release notes](https://github.com/DotNetAnalyzers/StyleCopAnalyzers/releases) - [Commits](https://github.com/DotNetAnalyzers/StyleCopAnalyzers/compare/1.2.0-beta.406...1.2.0-beta.435) --- updated-dependencies: - dependency-name: StyleCop.Analyzers dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Analyzers.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Analyzers.props b/Analyzers.props index d0dc67350f9..06b3ba96255 100644 --- a/Analyzers.props +++ b/Analyzers.props @@ -2,6 +2,6 @@ - + From 19b474fa3f9e170bf7ec1150f118a9559c6ad68f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Oct 2022 13:56:56 -0700 Subject: [PATCH 08/11] Bump Newtonsoft.Json from 10.0.1 to 13.0.1 in /test/tools/TestAlc/nested (#189) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- test/tools/TestAlc/nested/Test.Isolated.Nested.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/tools/TestAlc/nested/Test.Isolated.Nested.csproj b/test/tools/TestAlc/nested/Test.Isolated.Nested.csproj index 2f4a64332b9..725387f6ead 100644 --- a/test/tools/TestAlc/nested/Test.Isolated.Nested.csproj +++ b/test/tools/TestAlc/nested/Test.Isolated.Nested.csproj @@ -16,7 +16,7 @@ - + From f9e166f573399a5f7e7a25c9e2f354ec57b3bacb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Oct 2022 13:57:15 -0700 Subject: [PATCH 09/11] Bump Newtonsoft.Json from 12.0.1 to 13.0.1 in /test/perf/dotnet-tools/ResultsComparer (#187) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- test/perf/dotnet-tools/ResultsComparer/ResultsComparer.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/perf/dotnet-tools/ResultsComparer/ResultsComparer.csproj b/test/perf/dotnet-tools/ResultsComparer/ResultsComparer.csproj index 5274b08d613..5c187276454 100644 --- a/test/perf/dotnet-tools/ResultsComparer/ResultsComparer.csproj +++ b/test/perf/dotnet-tools/ResultsComparer/ResultsComparer.csproj @@ -8,7 +8,7 @@ - + From 56d12e6a524b55e322047bd7bba60f7327d77763 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Oct 2022 13:57:31 -0700 Subject: [PATCH 10/11] Bump Newtonsoft.Json from 12.0.2 to 13.0.1 in /test/perf/dotnet-tools/Reporting (#188) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- test/perf/dotnet-tools/Reporting/Reporting.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/perf/dotnet-tools/Reporting/Reporting.csproj b/test/perf/dotnet-tools/Reporting/Reporting.csproj index e0d2f3b8249..70447cf5d73 100644 --- a/test/perf/dotnet-tools/Reporting/Reporting.csproj +++ b/test/perf/dotnet-tools/Reporting/Reporting.csproj @@ -6,7 +6,7 @@ - + From cc569c3be04f4d67b5e5f744d3bb84761c95aab1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Nov 2022 18:03:58 +0000 Subject: [PATCH 11/11] Bump Newtonsoft.Json from 13.0.1 to 13.0.2 Bumps [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) from 13.0.1 to 13.0.2. - [Release notes](https://github.com/JamesNK/Newtonsoft.Json/releases) - [Commits](https://github.com/JamesNK/Newtonsoft.Json/compare/13.0.1...13.0.2) --- updated-dependencies: - dependency-name: Newtonsoft.Json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .../System.Management.Automation.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/System.Management.Automation/System.Management.Automation.csproj b/src/System.Management.Automation/System.Management.Automation.csproj index 56a1e8adeb3..0e992fd4de7 100644 --- a/src/System.Management.Automation/System.Management.Automation.csproj +++ b/src/System.Management.Automation/System.Management.Automation.csproj @@ -12,7 +12,7 @@ - +