Skip to content

Commit 2f38cd2

Browse files
authored
fix: support submodules when commit signing (#3354)
* fix: support submodules when commit signing * create correct tree object for submodule * update log messages
1 parent 7a8aeac commit 2f38cd2

5 files changed

+115
-74
lines changed

__test__/create-or-update-branch.int.test.ts

+25-14
Original file line numberDiff line numberDiff line change
@@ -250,11 +250,15 @@ describe('create-or-update-branch tests', () => {
250250
expect(branchCommits.length).toEqual(1)
251251
expect(branchCommits[0].subject).toEqual('Test changes')
252252
expect(branchCommits[0].changes.length).toEqual(3)
253-
expect(branchCommits[0].changes).toEqual([
254-
{mode: '100755', path: UNTRACKED_EXE_FILE, status: 'A'},
255-
{mode: '100644', path: TRACKED_FILE, status: 'M'},
256-
{mode: '100644', path: UNTRACKED_FILE, status: 'A'}
257-
])
253+
expect(branchCommits[0].changes[0].mode).toEqual('100755')
254+
expect(branchCommits[0].changes[0].path).toEqual(UNTRACKED_EXE_FILE)
255+
expect(branchCommits[0].changes[0].status).toEqual('A')
256+
expect(branchCommits[0].changes[1].mode).toEqual('100644')
257+
expect(branchCommits[0].changes[1].path).toEqual(TRACKED_FILE)
258+
expect(branchCommits[0].changes[1].status).toEqual('M')
259+
expect(branchCommits[0].changes[2].mode).toEqual('100644')
260+
expect(branchCommits[0].changes[2].path).toEqual(UNTRACKED_FILE)
261+
expect(branchCommits[0].changes[2].status).toEqual('A')
258262
})
259263

260264
it('tests buildBranchCommits with addition and deletion', async () => {
@@ -272,11 +276,15 @@ describe('create-or-update-branch tests', () => {
272276
expect(branchCommits.length).toEqual(1)
273277
expect(branchCommits[0].subject).toEqual('Test changes')
274278
expect(branchCommits[0].changes.length).toEqual(3)
275-
expect(branchCommits[0].changes).toEqual([
276-
{mode: '100644', path: TRACKED_FILE, status: 'D'},
277-
{mode: '100644', path: UNTRACKED_FILE, status: 'A'},
278-
{mode: '100644', path: TRACKED_FILE_NEW_PATH, status: 'A'}
279-
])
279+
expect(branchCommits[0].changes[0].mode).toEqual('100644')
280+
expect(branchCommits[0].changes[0].path).toEqual(TRACKED_FILE)
281+
expect(branchCommits[0].changes[0].status).toEqual('D')
282+
expect(branchCommits[0].changes[1].mode).toEqual('100644')
283+
expect(branchCommits[0].changes[1].path).toEqual(UNTRACKED_FILE)
284+
expect(branchCommits[0].changes[1].status).toEqual('A')
285+
expect(branchCommits[0].changes[2].mode).toEqual('100644')
286+
expect(branchCommits[0].changes[2].path).toEqual(TRACKED_FILE_NEW_PATH)
287+
expect(branchCommits[0].changes[2].status).toEqual('A')
280288
})
281289

282290
it('tests buildBranchCommits with multiple commits', async () => {
@@ -294,10 +302,13 @@ describe('create-or-update-branch tests', () => {
294302
expect(branchCommits[i].subject).toEqual(`Test changes ${i}`)
295303
expect(branchCommits[i].changes.length).toEqual(2)
296304
const untrackedFileStatus = i == 0 ? 'A' : 'M'
297-
expect(branchCommits[i].changes).toEqual([
298-
{mode: '100644', path: TRACKED_FILE, status: 'M'},
299-
{mode: '100644', path: UNTRACKED_FILE, status: untrackedFileStatus}
300-
])
305+
306+
expect(branchCommits[i].changes[0].mode).toEqual('100644')
307+
expect(branchCommits[i].changes[0].path).toEqual(TRACKED_FILE)
308+
expect(branchCommits[i].changes[0].status).toEqual('M')
309+
expect(branchCommits[i].changes[1].mode).toEqual('100644')
310+
expect(branchCommits[i].changes[1].path).toEqual(UNTRACKED_FILE)
311+
expect(branchCommits[i].changes[1].status).toEqual(untrackedFileStatus)
301312
}
302313
})
303314

__test__/git-command-manager.int.test.ts

+12-10
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ describe('git-command-manager integration tests', () => {
1818

1919
expect(initialCommit.subject).toEqual('initial commit')
2020
expect(initialCommit.signed).toBeFalsy()
21-
expect(initialCommit.changes).toEqual([
22-
{mode: '100644', status: 'A', path: 'README_TEMP.md'}
23-
])
21+
expect(initialCommit.changes[0].mode).toEqual('100644')
22+
expect(initialCommit.changes[0].status).toEqual('A')
23+
expect(initialCommit.changes[0].path).toEqual('README_TEMP.md')
2424

2525
expect(emptyCommit.subject).toEqual('empty commit for tests')
2626
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', () => {
3131
expect(modifiedCommit.subject).toEqual('add sparkles')
3232
expect(modifiedCommit.parents[0]).toEqual(emptyCommit.sha)
3333
expect(modifiedCommit.signed).toBeFalsy()
34-
expect(modifiedCommit.changes).toEqual([
35-
{mode: '100644', status: 'M', path: 'README_TEMP.md'}
36-
])
34+
expect(modifiedCommit.changes[0].mode).toEqual('100644')
35+
expect(modifiedCommit.changes[0].status).toEqual('M')
36+
expect(modifiedCommit.changes[0].path).toEqual('README_TEMP.md')
3737

3838
expect(headCommit.subject).toEqual('rename readme')
3939
expect(headCommit.parents[0]).toEqual(modifiedCommit.sha)
4040
expect(headCommit.signed).toBeFalsy()
41-
expect(headCommit.changes).toEqual([
42-
{mode: '100644', status: 'A', path: 'README.md'},
43-
{mode: '100644', status: 'D', path: 'README_TEMP.md'}
44-
])
41+
expect(headCommit.changes[0].mode).toEqual('100644')
42+
expect(headCommit.changes[0].status).toEqual('A')
43+
expect(headCommit.changes[0].path).toEqual('README.md')
44+
expect(headCommit.changes[1].mode).toEqual('100644')
45+
expect(headCommit.changes[1].status).toEqual('D')
46+
expect(headCommit.changes[1].path).toEqual('README_TEMP.md')
4547
})
4648
})

dist/index.js

+34-21
Original file line numberDiff line numberDiff line change
@@ -762,12 +762,13 @@ class GitCommandManager {
762762
subject: detailLines[4],
763763
body: detailLines.slice(5, endOfBodyIndex).join('\n'),
764764
changes: lines.slice(endOfBodyIndex + 2, -1).map(line => {
765-
const change = line.match(/^:(\d{6}) (\d{6}) \w{40} \w{40} ([AMD])\s+(.*)$/);
765+
const change = line.match(/^:(\d{6}) (\d{6}) \w{40} (\w{40}) ([AMD])\s+(.*)$/);
766766
if (change) {
767767
return {
768-
mode: change[3] === 'D' ? change[1] : change[2],
769-
status: change[3],
770-
path: change[4]
768+
mode: change[4] === 'D' ? change[1] : change[2],
769+
dstSha: change[3],
770+
status: change[4],
771+
path: change[5]
771772
};
772773
}
773774
else {
@@ -1368,25 +1369,37 @@ class GitHubHelper {
13681369
let treeSha = parentCommit.tree;
13691370
if (commit.changes.length > 0) {
13701371
core.info(`Creating tree objects for local commit ${commit.sha}`);
1371-
const treeObjects = yield Promise.all(commit.changes.map((_a) => __awaiter(this, [_a], void 0, function* ({ path, mode, status }) {
1372-
let sha = null;
1373-
if (status === 'A' || status === 'M') {
1374-
try {
1375-
const { data: blob } = yield blobCreationLimit(() => this.octokit.rest.git.createBlob(Object.assign(Object.assign({}, repository), { content: utils.readFileBase64([repoPath, path]), encoding: 'base64' })));
1376-
sha = blob.sha;
1377-
}
1378-
catch (error) {
1379-
core.error(`Error creating blob for file '${path}': ${utils.getErrorMessage(error)}`);
1380-
throw error;
1372+
const treeObjects = yield Promise.all(commit.changes.map((_a) => __awaiter(this, [_a], void 0, function* ({ path, mode, status, dstSha }) {
1373+
if (mode === '160000') {
1374+
// submodule
1375+
core.info(`Creating tree object for submodule commit at '${path}'`);
1376+
return {
1377+
path,
1378+
mode,
1379+
sha: dstSha,
1380+
type: 'commit'
1381+
};
1382+
}
1383+
else {
1384+
let sha = null;
1385+
if (status === 'A' || status === 'M') {
1386+
try {
1387+
const { data: blob } = yield blobCreationLimit(() => this.octokit.rest.git.createBlob(Object.assign(Object.assign({}, repository), { content: utils.readFileBase64([repoPath, path]), encoding: 'base64' })));
1388+
sha = blob.sha;
1389+
}
1390+
catch (error) {
1391+
core.error(`Error creating blob for file '${path}': ${utils.getErrorMessage(error)}`);
1392+
throw error;
1393+
}
13811394
}
1395+
core.info(`Creating tree object for blob at '${path}' with status '${status}'`);
1396+
return {
1397+
path,
1398+
mode,
1399+
sha,
1400+
type: 'blob'
1401+
};
13821402
}
1383-
core.info(`Created blob for file '${path}'`);
1384-
return {
1385-
path,
1386-
mode,
1387-
sha,
1388-
type: 'blob'
1389-
};
13901403
})));
13911404
const chunkSize = 100;
13921405
const chunkedTreeObjects = Array.from({ length: Math.ceil(treeObjects.length / chunkSize) }, (_, i) => treeObjects.slice(i * chunkSize, i * chunkSize + chunkSize));

src/git-command-manager.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export type Commit = {
1414
body: string
1515
changes: {
1616
mode: string
17+
dstSha: string
1718
status: 'A' | 'M' | 'D'
1819
path: string
1920
}[]
@@ -178,13 +179,14 @@ export class GitCommandManager {
178179
body: detailLines.slice(5, endOfBodyIndex).join('\n'),
179180
changes: lines.slice(endOfBodyIndex + 2, -1).map(line => {
180181
const change = line.match(
181-
/^:(\d{6}) (\d{6}) \w{40} \w{40} ([AMD])\s+(.*)$/
182+
/^:(\d{6}) (\d{6}) \w{40} (\w{40}) ([AMD])\s+(.*)$/
182183
)
183184
if (change) {
184185
return {
185-
mode: change[3] === 'D' ? change[1] : change[2],
186-
status: change[3],
187-
path: change[4]
186+
mode: change[4] === 'D' ? change[1] : change[2],
187+
dstSha: change[3],
188+
status: change[4],
189+
path: change[5]
188190
}
189191
} else {
190192
unparsedChanges.push(line)

src/github-helper.ts

+38-25
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ type TreeObject = {
3535
path: string
3636
mode: '100644' | '100755' | '040000' | '160000' | '120000'
3737
sha: string | null
38-
type: 'blob'
38+
type: 'blob' | 'commit'
3939
}
4040

4141
export class GitHubHelper {
@@ -255,31 +255,44 @@ export class GitHubHelper {
255255
if (commit.changes.length > 0) {
256256
core.info(`Creating tree objects for local commit ${commit.sha}`)
257257
const treeObjects = await Promise.all(
258-
commit.changes.map(async ({path, mode, status}) => {
259-
let sha: string | null = null
260-
if (status === 'A' || status === 'M') {
261-
try {
262-
const {data: blob} = await blobCreationLimit(() =>
263-
this.octokit.rest.git.createBlob({
264-
...repository,
265-
content: utils.readFileBase64([repoPath, path]),
266-
encoding: 'base64'
267-
})
268-
)
269-
sha = blob.sha
270-
} catch (error) {
271-
core.error(
272-
`Error creating blob for file '${path}': ${utils.getErrorMessage(error)}`
273-
)
274-
throw error
258+
commit.changes.map(async ({path, mode, status, dstSha}) => {
259+
if (mode === '160000') {
260+
// submodule
261+
core.info(`Creating tree object for submodule commit at '${path}'`)
262+
return <TreeObject>{
263+
path,
264+
mode,
265+
sha: dstSha,
266+
type: 'commit'
267+
}
268+
} else {
269+
let sha: string | null = null
270+
if (status === 'A' || status === 'M') {
271+
try {
272+
const {data: blob} = await blobCreationLimit(() =>
273+
this.octokit.rest.git.createBlob({
274+
...repository,
275+
content: utils.readFileBase64([repoPath, path]),
276+
encoding: 'base64'
277+
})
278+
)
279+
sha = blob.sha
280+
} catch (error) {
281+
core.error(
282+
`Error creating blob for file '${path}': ${utils.getErrorMessage(error)}`
283+
)
284+
throw error
285+
}
286+
}
287+
core.info(
288+
`Creating tree object for blob at '${path}' with status '${status}'`
289+
)
290+
return <TreeObject>{
291+
path,
292+
mode,
293+
sha,
294+
type: 'blob'
275295
}
276-
}
277-
core.info(`Created blob for file '${path}'`)
278-
return <TreeObject>{
279-
path,
280-
mode,
281-
sha,
282-
type: 'blob'
283296
}
284297
})
285298
)

0 commit comments

Comments
 (0)