fix: support submodules when commit signing (#3354)
* fix: support submodules when commit signing * create correct tree object for submodule * update log messages
This commit is contained in:
parent
7a8aeac749
commit
2f38cd26bf
5 changed files with 116 additions and 75 deletions
|
@ -250,11 +250,15 @@ describe('create-or-update-branch tests', () => {
|
||||||
expect(branchCommits.length).toEqual(1)
|
expect(branchCommits.length).toEqual(1)
|
||||||
expect(branchCommits[0].subject).toEqual('Test changes')
|
expect(branchCommits[0].subject).toEqual('Test changes')
|
||||||
expect(branchCommits[0].changes.length).toEqual(3)
|
expect(branchCommits[0].changes.length).toEqual(3)
|
||||||
expect(branchCommits[0].changes).toEqual([
|
expect(branchCommits[0].changes[0].mode).toEqual('100755')
|
||||||
{mode: '100755', path: UNTRACKED_EXE_FILE, status: 'A'},
|
expect(branchCommits[0].changes[0].path).toEqual(UNTRACKED_EXE_FILE)
|
||||||
{mode: '100644', path: TRACKED_FILE, status: 'M'},
|
expect(branchCommits[0].changes[0].status).toEqual('A')
|
||||||
{mode: '100644', path: UNTRACKED_FILE, status: 'A'}
|
expect(branchCommits[0].changes[1].mode).toEqual('100644')
|
||||||
])
|
expect(branchCommits[0].changes[1].path).toEqual(TRACKED_FILE)
|
||||||
|
expect(branchCommits[0].changes[1].status).toEqual('M')
|
||||||
|
expect(branchCommits[0].changes[2].mode).toEqual('100644')
|
||||||
|
expect(branchCommits[0].changes[2].path).toEqual(UNTRACKED_FILE)
|
||||||
|
expect(branchCommits[0].changes[2].status).toEqual('A')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('tests buildBranchCommits with addition and deletion', async () => {
|
it('tests buildBranchCommits with addition and deletion', async () => {
|
||||||
|
@ -272,11 +276,15 @@ describe('create-or-update-branch tests', () => {
|
||||||
expect(branchCommits.length).toEqual(1)
|
expect(branchCommits.length).toEqual(1)
|
||||||
expect(branchCommits[0].subject).toEqual('Test changes')
|
expect(branchCommits[0].subject).toEqual('Test changes')
|
||||||
expect(branchCommits[0].changes.length).toEqual(3)
|
expect(branchCommits[0].changes.length).toEqual(3)
|
||||||
expect(branchCommits[0].changes).toEqual([
|
expect(branchCommits[0].changes[0].mode).toEqual('100644')
|
||||||
{mode: '100644', path: TRACKED_FILE, status: 'D'},
|
expect(branchCommits[0].changes[0].path).toEqual(TRACKED_FILE)
|
||||||
{mode: '100644', path: UNTRACKED_FILE, status: 'A'},
|
expect(branchCommits[0].changes[0].status).toEqual('D')
|
||||||
{mode: '100644', path: TRACKED_FILE_NEW_PATH, status: 'A'}
|
expect(branchCommits[0].changes[1].mode).toEqual('100644')
|
||||||
])
|
expect(branchCommits[0].changes[1].path).toEqual(UNTRACKED_FILE)
|
||||||
|
expect(branchCommits[0].changes[1].status).toEqual('A')
|
||||||
|
expect(branchCommits[0].changes[2].mode).toEqual('100644')
|
||||||
|
expect(branchCommits[0].changes[2].path).toEqual(TRACKED_FILE_NEW_PATH)
|
||||||
|
expect(branchCommits[0].changes[2].status).toEqual('A')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('tests buildBranchCommits with multiple commits', async () => {
|
it('tests buildBranchCommits with multiple commits', async () => {
|
||||||
|
@ -294,10 +302,13 @@ describe('create-or-update-branch tests', () => {
|
||||||
expect(branchCommits[i].subject).toEqual(`Test changes ${i}`)
|
expect(branchCommits[i].subject).toEqual(`Test changes ${i}`)
|
||||||
expect(branchCommits[i].changes.length).toEqual(2)
|
expect(branchCommits[i].changes.length).toEqual(2)
|
||||||
const untrackedFileStatus = i == 0 ? 'A' : 'M'
|
const untrackedFileStatus = i == 0 ? 'A' : 'M'
|
||||||
expect(branchCommits[i].changes).toEqual([
|
|
||||||
{mode: '100644', path: TRACKED_FILE, status: 'M'},
|
expect(branchCommits[i].changes[0].mode).toEqual('100644')
|
||||||
{mode: '100644', path: UNTRACKED_FILE, status: untrackedFileStatus}
|
expect(branchCommits[i].changes[0].path).toEqual(TRACKED_FILE)
|
||||||
])
|
expect(branchCommits[i].changes[0].status).toEqual('M')
|
||||||
|
expect(branchCommits[i].changes[1].mode).toEqual('100644')
|
||||||
|
expect(branchCommits[i].changes[1].path).toEqual(UNTRACKED_FILE)
|
||||||
|
expect(branchCommits[i].changes[1].status).toEqual(untrackedFileStatus)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,9 @@ describe('git-command-manager integration tests', () => {
|
||||||
|
|
||||||
expect(initialCommit.subject).toEqual('initial commit')
|
expect(initialCommit.subject).toEqual('initial commit')
|
||||||
expect(initialCommit.signed).toBeFalsy()
|
expect(initialCommit.signed).toBeFalsy()
|
||||||
expect(initialCommit.changes).toEqual([
|
expect(initialCommit.changes[0].mode).toEqual('100644')
|
||||||
{mode: '100644', status: 'A', path: 'README_TEMP.md'}
|
expect(initialCommit.changes[0].status).toEqual('A')
|
||||||
])
|
expect(initialCommit.changes[0].path).toEqual('README_TEMP.md')
|
||||||
|
|
||||||
expect(emptyCommit.subject).toEqual('empty commit for tests')
|
expect(emptyCommit.subject).toEqual('empty commit for tests')
|
||||||
expect(emptyCommit.tree).toEqual(initialCommit.tree) // empty commits have no tree and reference the parent's
|
expect(emptyCommit.tree).toEqual(initialCommit.tree) // empty commits have no tree and reference the parent's
|
||||||
|
@ -31,16 +31,18 @@ describe('git-command-manager integration tests', () => {
|
||||||
expect(modifiedCommit.subject).toEqual('add sparkles')
|
expect(modifiedCommit.subject).toEqual('add sparkles')
|
||||||
expect(modifiedCommit.parents[0]).toEqual(emptyCommit.sha)
|
expect(modifiedCommit.parents[0]).toEqual(emptyCommit.sha)
|
||||||
expect(modifiedCommit.signed).toBeFalsy()
|
expect(modifiedCommit.signed).toBeFalsy()
|
||||||
expect(modifiedCommit.changes).toEqual([
|
expect(modifiedCommit.changes[0].mode).toEqual('100644')
|
||||||
{mode: '100644', status: 'M', path: 'README_TEMP.md'}
|
expect(modifiedCommit.changes[0].status).toEqual('M')
|
||||||
])
|
expect(modifiedCommit.changes[0].path).toEqual('README_TEMP.md')
|
||||||
|
|
||||||
expect(headCommit.subject).toEqual('rename readme')
|
expect(headCommit.subject).toEqual('rename readme')
|
||||||
expect(headCommit.parents[0]).toEqual(modifiedCommit.sha)
|
expect(headCommit.parents[0]).toEqual(modifiedCommit.sha)
|
||||||
expect(headCommit.signed).toBeFalsy()
|
expect(headCommit.signed).toBeFalsy()
|
||||||
expect(headCommit.changes).toEqual([
|
expect(headCommit.changes[0].mode).toEqual('100644')
|
||||||
{mode: '100644', status: 'A', path: 'README.md'},
|
expect(headCommit.changes[0].status).toEqual('A')
|
||||||
{mode: '100644', status: 'D', path: 'README_TEMP.md'}
|
expect(headCommit.changes[0].path).toEqual('README.md')
|
||||||
])
|
expect(headCommit.changes[1].mode).toEqual('100644')
|
||||||
|
expect(headCommit.changes[1].status).toEqual('D')
|
||||||
|
expect(headCommit.changes[1].path).toEqual('README_TEMP.md')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
57
dist/index.js
vendored
57
dist/index.js
vendored
|
@ -762,12 +762,13 @@ class GitCommandManager {
|
||||||
subject: detailLines[4],
|
subject: detailLines[4],
|
||||||
body: detailLines.slice(5, endOfBodyIndex).join('\n'),
|
body: detailLines.slice(5, endOfBodyIndex).join('\n'),
|
||||||
changes: lines.slice(endOfBodyIndex + 2, -1).map(line => {
|
changes: lines.slice(endOfBodyIndex + 2, -1).map(line => {
|
||||||
const change = line.match(/^:(\d{6}) (\d{6}) \w{40} \w{40} ([AMD])\s+(.*)$/);
|
const change = line.match(/^:(\d{6}) (\d{6}) \w{40} (\w{40}) ([AMD])\s+(.*)$/);
|
||||||
if (change) {
|
if (change) {
|
||||||
return {
|
return {
|
||||||
mode: change[3] === 'D' ? change[1] : change[2],
|
mode: change[4] === 'D' ? change[1] : change[2],
|
||||||
status: change[3],
|
dstSha: change[3],
|
||||||
path: change[4]
|
status: change[4],
|
||||||
|
path: change[5]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1368,25 +1369,37 @@ class GitHubHelper {
|
||||||
let treeSha = parentCommit.tree;
|
let treeSha = parentCommit.tree;
|
||||||
if (commit.changes.length > 0) {
|
if (commit.changes.length > 0) {
|
||||||
core.info(`Creating tree objects for local commit ${commit.sha}`);
|
core.info(`Creating tree objects for local commit ${commit.sha}`);
|
||||||
const treeObjects = yield Promise.all(commit.changes.map((_a) => __awaiter(this, [_a], void 0, function* ({ path, mode, status }) {
|
const treeObjects = yield Promise.all(commit.changes.map((_a) => __awaiter(this, [_a], void 0, function* ({ path, mode, status, dstSha }) {
|
||||||
let sha = null;
|
if (mode === '160000') {
|
||||||
if (status === 'A' || status === 'M') {
|
// submodule
|
||||||
try {
|
core.info(`Creating tree object for submodule commit at '${path}'`);
|
||||||
const { data: blob } = yield blobCreationLimit(() => this.octokit.rest.git.createBlob(Object.assign(Object.assign({}, repository), { content: utils.readFileBase64([repoPath, path]), encoding: 'base64' })));
|
return {
|
||||||
sha = blob.sha;
|
path,
|
||||||
}
|
mode,
|
||||||
catch (error) {
|
sha: dstSha,
|
||||||
core.error(`Error creating blob for file '${path}': ${utils.getErrorMessage(error)}`);
|
type: 'commit'
|
||||||
throw error;
|
};
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
let sha = null;
|
||||||
|
if (status === 'A' || status === 'M') {
|
||||||
|
try {
|
||||||
|
const { data: blob } = yield blobCreationLimit(() => this.octokit.rest.git.createBlob(Object.assign(Object.assign({}, repository), { content: utils.readFileBase64([repoPath, path]), encoding: 'base64' })));
|
||||||
|
sha = blob.sha;
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
core.error(`Error creating blob for file '${path}': ${utils.getErrorMessage(error)}`);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
core.info(`Creating tree object for blob at '${path}' with status '${status}'`);
|
||||||
|
return {
|
||||||
|
path,
|
||||||
|
mode,
|
||||||
|
sha,
|
||||||
|
type: 'blob'
|
||||||
|
};
|
||||||
}
|
}
|
||||||
core.info(`Created blob for file '${path}'`);
|
|
||||||
return {
|
|
||||||
path,
|
|
||||||
mode,
|
|
||||||
sha,
|
|
||||||
type: 'blob'
|
|
||||||
};
|
|
||||||
})));
|
})));
|
||||||
const chunkSize = 100;
|
const chunkSize = 100;
|
||||||
const chunkedTreeObjects = Array.from({ length: Math.ceil(treeObjects.length / chunkSize) }, (_, i) => treeObjects.slice(i * chunkSize, i * chunkSize + chunkSize));
|
const chunkedTreeObjects = Array.from({ length: Math.ceil(treeObjects.length / chunkSize) }, (_, i) => treeObjects.slice(i * chunkSize, i * chunkSize + chunkSize));
|
||||||
|
|
|
@ -14,6 +14,7 @@ export type Commit = {
|
||||||
body: string
|
body: string
|
||||||
changes: {
|
changes: {
|
||||||
mode: string
|
mode: string
|
||||||
|
dstSha: string
|
||||||
status: 'A' | 'M' | 'D'
|
status: 'A' | 'M' | 'D'
|
||||||
path: string
|
path: string
|
||||||
}[]
|
}[]
|
||||||
|
@ -178,13 +179,14 @@ export class GitCommandManager {
|
||||||
body: detailLines.slice(5, endOfBodyIndex).join('\n'),
|
body: detailLines.slice(5, endOfBodyIndex).join('\n'),
|
||||||
changes: lines.slice(endOfBodyIndex + 2, -1).map(line => {
|
changes: lines.slice(endOfBodyIndex + 2, -1).map(line => {
|
||||||
const change = line.match(
|
const change = line.match(
|
||||||
/^:(\d{6}) (\d{6}) \w{40} \w{40} ([AMD])\s+(.*)$/
|
/^:(\d{6}) (\d{6}) \w{40} (\w{40}) ([AMD])\s+(.*)$/
|
||||||
)
|
)
|
||||||
if (change) {
|
if (change) {
|
||||||
return {
|
return {
|
||||||
mode: change[3] === 'D' ? change[1] : change[2],
|
mode: change[4] === 'D' ? change[1] : change[2],
|
||||||
status: change[3],
|
dstSha: change[3],
|
||||||
path: change[4]
|
status: change[4],
|
||||||
|
path: change[5]
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
unparsedChanges.push(line)
|
unparsedChanges.push(line)
|
||||||
|
|
|
@ -35,7 +35,7 @@ type TreeObject = {
|
||||||
path: string
|
path: string
|
||||||
mode: '100644' | '100755' | '040000' | '160000' | '120000'
|
mode: '100644' | '100755' | '040000' | '160000' | '120000'
|
||||||
sha: string | null
|
sha: string | null
|
||||||
type: 'blob'
|
type: 'blob' | 'commit'
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GitHubHelper {
|
export class GitHubHelper {
|
||||||
|
@ -255,31 +255,44 @@ export class GitHubHelper {
|
||||||
if (commit.changes.length > 0) {
|
if (commit.changes.length > 0) {
|
||||||
core.info(`Creating tree objects for local commit ${commit.sha}`)
|
core.info(`Creating tree objects for local commit ${commit.sha}`)
|
||||||
const treeObjects = await Promise.all(
|
const treeObjects = await Promise.all(
|
||||||
commit.changes.map(async ({path, mode, status}) => {
|
commit.changes.map(async ({path, mode, status, dstSha}) => {
|
||||||
let sha: string | null = null
|
if (mode === '160000') {
|
||||||
if (status === 'A' || status === 'M') {
|
// submodule
|
||||||
try {
|
core.info(`Creating tree object for submodule commit at '${path}'`)
|
||||||
const {data: blob} = await blobCreationLimit(() =>
|
return <TreeObject>{
|
||||||
this.octokit.rest.git.createBlob({
|
path,
|
||||||
...repository,
|
mode,
|
||||||
content: utils.readFileBase64([repoPath, path]),
|
sha: dstSha,
|
||||||
encoding: 'base64'
|
type: 'commit'
|
||||||
})
|
}
|
||||||
)
|
} else {
|
||||||
sha = blob.sha
|
let sha: string | null = null
|
||||||
} catch (error) {
|
if (status === 'A' || status === 'M') {
|
||||||
core.error(
|
try {
|
||||||
`Error creating blob for file '${path}': ${utils.getErrorMessage(error)}`
|
const {data: blob} = await blobCreationLimit(() =>
|
||||||
)
|
this.octokit.rest.git.createBlob({
|
||||||
throw error
|
...repository,
|
||||||
|
content: utils.readFileBase64([repoPath, path]),
|
||||||
|
encoding: 'base64'
|
||||||
|
})
|
||||||
|
)
|
||||||
|
sha = blob.sha
|
||||||
|
} catch (error) {
|
||||||
|
core.error(
|
||||||
|
`Error creating blob for file '${path}': ${utils.getErrorMessage(error)}`
|
||||||
|
)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
core.info(
|
||||||
|
`Creating tree object for blob at '${path}' with status '${status}'`
|
||||||
|
)
|
||||||
|
return <TreeObject>{
|
||||||
|
path,
|
||||||
|
mode,
|
||||||
|
sha,
|
||||||
|
type: 'blob'
|
||||||
}
|
}
|
||||||
}
|
|
||||||
core.info(`Created blob for file '${path}'`)
|
|
||||||
return <TreeObject>{
|
|
||||||
path,
|
|
||||||
mode,
|
|
||||||
sha,
|
|
||||||
type: 'blob'
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue