There are multiple bugs in actions/setup/js/push_signed_commits.cjs which will silently push incorrect content.
There's probably some more, but there are the ones I noticed while doing some research of existing code before I ended up making my own action for pushing signed commits.
copies in diffs are treated like renames
|
} else if (status.startsWith("R") || status.startsWith("C")) { |
|
// Rename or Copy: parts[1] = old path, parts[2] = new path |
|
deletions.push({ path: parts[1] }); |
|
const content = fs.readFileSync(path.join(cwd, parts[2])); |
|
additions.push({ path: parts[2], contents: content.toString("base64") }); |
|
} else { |
The old file is deleted, even if it's a copy. This needs to be surrounded by another check for if it's specifically a rename versus a copy.
git diff may double-quote filenames
|
// File changes for this commit (supports Add/Modify/Delete/Rename/Copy) |
|
const { stdout: nameStatusOut } = await exec.getExecOutput("git", ["diff", "--name-status", `${sha}^`, sha], { cwd }); |
|
/** @type {Array<{path: string, contents: string}>} */ |
|
const additions = []; |
|
/** @type {Array<{path: string}>} */ |
|
const deletions = []; |
|
|
|
for (const line of nameStatusOut.trim().split("\n").filter(Boolean)) { |
|
const parts = line.split("\t"); |
|
const status = parts[0]; |
That is not handled here. The git diff command may c-quote filenames with special characters. The code should check if the names start with double-quotes and unescape them if so.
Also, git diff-tree is better than git diff since it won't be affected by the git config.
the working tree content is always used
|
const content = fs.readFileSync(path.join(cwd, parts[2])); |
|
additions.push({ path: parts[2], contents: content.toString("base64") }); |
|
} else { |
|
// Added or Modified |
|
const content = fs.readFileSync(path.join(cwd, parts[1])); |
This is incorrect since the content in the last commit may not be the same as the working area, and the content in old commits will be incorrect.
The git show REV:PATH command or git ls-tree combined with git cat-files should be used instead.
merge commits are not handled
git rev-list will list commits from both parents
createCommitOnBranch doesn't support creating commits with multiple parents.
submodule updates will fail to be pushed
They appear as a single item in git diff, point to a commit object in the tree (rather than a blob), and will be a directory in the working area.
Furthermore, the GitHub GraphQL API createCommitOnBranch mutation doesn't support submodules (this is an easy fix though, see below).
git rev-list lists by commit date by default
|
const { stdout: revListOut } = await exec.getExecOutput("git", ["rev-list", "--reverse", `${baseRef}..HEAD`], { cwd }); |
|
const shas = revListOut.trim().split("\n").filter(Boolean); |
Commits with out-of-order commit dates (e.g., ones rebased with --committer-date-is-author-date) will not be pushed in the correct order. The --topo-order option should be used to ensure they are listed in graph order.
non-100644 file modes are silently discarded
Things like shell scripts typically have 100755 permissions, but these will be silently dropped when the file is modified and pushed since the createCommitOnBranch mutation doesn't support them.
Symlinks will be silently converted to a regular file with the contents of the target, and will fail if it's a directory.
See https://github.com/orgs/community/discussions/191953.
There are multiple bugs in actions/setup/js/push_signed_commits.cjs which will silently push incorrect content.
There's probably some more, but there are the ones I noticed while doing some research of existing code before I ended up making my own action for pushing signed commits.
copies in diffs are treated like renames
gh-aw/actions/setup/js/push_signed_commits.cjs
Lines 125 to 130 in 4fba480
The old file is deleted, even if it's a copy. This needs to be surrounded by another check for if it's specifically a rename versus a copy.
git diff may double-quote filenames
gh-aw/actions/setup/js/push_signed_commits.cjs
Lines 113 to 122 in 4fba480
That is not handled here. The
git diffcommand may c-quote filenames with special characters. The code should check if the names start with double-quotes and unescape them if so.Also,
git diff-treeis better thangit diffsince it won't be affected by the git config.the working tree content is always used
gh-aw/actions/setup/js/push_signed_commits.cjs
Lines 128 to 132 in 4fba480
This is incorrect since the content in the last commit may not be the same as the working area, and the content in old commits will be incorrect.
The
git show REV:PATHcommand orgit ls-treecombined withgit cat-filesshould be used instead.merge commits are not handled
git rev-listwill list commits from both parentscreateCommitOnBranchdoesn't support creating commits with multiple parents.submodule updates will fail to be pushed
They appear as a single item in
git diff, point to a commit object in the tree (rather than a blob), and will be a directory in the working area.Furthermore, the GitHub GraphQL API
createCommitOnBranchmutation doesn't support submodules (this is an easy fix though, see below).git rev-list lists by commit date by default
gh-aw/actions/setup/js/push_signed_commits.cjs
Lines 40 to 41 in 4fba480
Commits with out-of-order commit dates (e.g., ones rebased with
--committer-date-is-author-date) will not be pushed in the correct order. The--topo-orderoption should be used to ensure they are listed in graph order.non-100644 file modes are silently discarded
Things like shell scripts typically have
100755permissions, but these will be silently dropped when the file is modified and pushed since thecreateCommitOnBranchmutation doesn't support them.Symlinks will be silently converted to a regular file with the contents of the target, and will fail if it's a directory.
See https://github.com/orgs/community/discussions/191953.