From fdee554557a0ce006682f929f6174d6f0d249970 Mon Sep 17 00:00:00 2001 From: Rajath Agasthya Date: Mon, 14 Sep 2026 18:12:35 -0500 Subject: [PATCH] Re-create backport commits via the Git Data API so they are verified main, release-0.14 and release-0.15 require signed commits, but the cherry-pick workflow pushes backport commits with git push from the runner, which never signs them. Every open backport PR to release-0.15 (#496 through #499) is currently blocked on an unsigned commit. After the push, re-create each new commit on the backport branch through the Git Data API, chaining from the target branch head, and force-point the backport branch at the new tip. GitHub signs commits created this way, so the chain shows as "Verified" without managing a GPG or SSH key for the bot. The initial push is kept because the API needs the tree objects to exist in the repository before the commits can be created. The re-created commits are authored by github-actions[bot]; the original commit stays referenced through the cherry-pick trailer. Ported from NVIDIA/nvidia-container-toolkit#2012. Signed-off-by: Rajath Agasthya --- .github/scripts/backport.js | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/.github/scripts/backport.js b/.github/scripts/backport.js index df73ce9b..32bc42a6 100644 --- a/.github/scripts/backport.js +++ b/.github/scripts/backport.js @@ -100,7 +100,42 @@ for (const targetBranch of branches) { // Push the backport branch (force to handle updates) core.info(`Pushing ${backportBranch} to origin`); execSync(`git push --force-with-lease origin ${backportBranch}`, { stdio: 'inherit' }); - + + // Re-create each new commit through the Git Data API so the resulting chain shows as "Verified" + core.info(`Re-creating commits via the Git Data API to get verified signatures`); + const newCommitShas = execSync(`git log --format=%H ${targetBranch}..${backportBranch}`, { encoding: 'utf-8' }) + .trim().split('\n').filter(Boolean).reverse(); // oldest -> newest + + const { data: baseRef } = await github.rest.git.getRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: `heads/${targetBranch}` + }); + let parentSha = baseRef.object.sha; + + for (const sha of newCommitShas) { + const treeSha = execSync(`git rev-parse ${sha}^{tree}`, { encoding: 'utf-8' }).trim(); + const message = execSync(`git log -1 --format=%B ${sha}`, { encoding: 'utf-8' }); + + const { data: newCommit } = await github.rest.git.createCommit({ + owner: context.repo.owner, + repo: context.repo.repo, + message, + tree: treeSha, + parents: [parentSha] + }); + parentSha = newCommit.sha; + } + + core.info(`Repointing ${backportBranch} at signed commit ${parentSha}`); + await github.rest.git.updateRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: `heads/${backportBranch}`, + sha: parentSha, + force: true + }); + // Check if a PR already exists for this backport branch const { data: existingPRs } = await github.rest.pulls.list({ owner: context.repo.owner,