Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: support submodules when commit signing #3354

Merged
merged 3 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 25 additions & 14 deletions __test__/create-or-update-branch.int.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,11 +250,15 @@ describe('create-or-update-branch tests', () => {
expect(branchCommits.length).toEqual(1)
expect(branchCommits[0].subject).toEqual('Test changes')
expect(branchCommits[0].changes.length).toEqual(3)
expect(branchCommits[0].changes).toEqual([
{mode: '100755', path: UNTRACKED_EXE_FILE, status: 'A'},
{mode: '100644', path: TRACKED_FILE, status: 'M'},
{mode: '100644', path: UNTRACKED_FILE, status: 'A'}
])
expect(branchCommits[0].changes[0].mode).toEqual('100755')
expect(branchCommits[0].changes[0].path).toEqual(UNTRACKED_EXE_FILE)
expect(branchCommits[0].changes[0].status).toEqual('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 () => {
Expand All @@ -272,11 +276,15 @@ describe('create-or-update-branch tests', () => {
expect(branchCommits.length).toEqual(1)
expect(branchCommits[0].subject).toEqual('Test changes')
expect(branchCommits[0].changes.length).toEqual(3)
expect(branchCommits[0].changes).toEqual([
{mode: '100644', path: TRACKED_FILE, status: 'D'},
{mode: '100644', path: UNTRACKED_FILE, status: 'A'},
{mode: '100644', path: TRACKED_FILE_NEW_PATH, status: 'A'}
])
expect(branchCommits[0].changes[0].mode).toEqual('100644')
expect(branchCommits[0].changes[0].path).toEqual(TRACKED_FILE)
expect(branchCommits[0].changes[0].status).toEqual('D')
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 () => {
Expand All @@ -294,10 +302,13 @@ describe('create-or-update-branch tests', () => {
expect(branchCommits[i].subject).toEqual(`Test changes ${i}`)
expect(branchCommits[i].changes.length).toEqual(2)
const untrackedFileStatus = i == 0 ? 'A' : 'M'
expect(branchCommits[i].changes).toEqual([
{mode: '100644', path: TRACKED_FILE, status: 'M'},
{mode: '100644', path: UNTRACKED_FILE, status: untrackedFileStatus}
])

expect(branchCommits[i].changes[0].mode).toEqual('100644')
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)
}
})

Expand Down
22 changes: 12 additions & 10 deletions __test__/git-command-manager.int.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ describe('git-command-manager integration tests', () => {

expect(initialCommit.subject).toEqual('initial commit')
expect(initialCommit.signed).toBeFalsy()
expect(initialCommit.changes).toEqual([
{mode: '100644', status: 'A', path: 'README_TEMP.md'}
])
expect(initialCommit.changes[0].mode).toEqual('100644')
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.tree).toEqual(initialCommit.tree) // empty commits have no tree and reference the parent's
Expand All @@ -31,16 +31,18 @@ describe('git-command-manager integration tests', () => {
expect(modifiedCommit.subject).toEqual('add sparkles')
expect(modifiedCommit.parents[0]).toEqual(emptyCommit.sha)
expect(modifiedCommit.signed).toBeFalsy()
expect(modifiedCommit.changes).toEqual([
{mode: '100644', status: 'M', path: 'README_TEMP.md'}
])
expect(modifiedCommit.changes[0].mode).toEqual('100644')
expect(modifiedCommit.changes[0].status).toEqual('M')
expect(modifiedCommit.changes[0].path).toEqual('README_TEMP.md')

expect(headCommit.subject).toEqual('rename readme')
expect(headCommit.parents[0]).toEqual(modifiedCommit.sha)
expect(headCommit.signed).toBeFalsy()
expect(headCommit.changes).toEqual([
{mode: '100644', status: 'A', path: 'README.md'},
{mode: '100644', status: 'D', path: 'README_TEMP.md'}
])
expect(headCommit.changes[0].mode).toEqual('100644')
expect(headCommit.changes[0].status).toEqual('A')
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')
})
})
55 changes: 34 additions & 21 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -762,12 +762,13 @@ class GitCommandManager {
subject: detailLines[4],
body: detailLines.slice(5, endOfBodyIndex).join('\n'),
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) {
return {
mode: change[3] === 'D' ? change[1] : change[2],
status: change[3],
path: change[4]
mode: change[4] === 'D' ? change[1] : change[2],
dstSha: change[3],
status: change[4],
path: change[5]
};
}
else {
Expand Down Expand Up @@ -1368,25 +1369,37 @@ class GitHubHelper {
let treeSha = parentCommit.tree;
if (commit.changes.length > 0) {
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 }) {
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;
const treeObjects = yield Promise.all(commit.changes.map((_a) => __awaiter(this, [_a], void 0, function* ({ path, mode, status, dstSha }) {
if (mode === '160000') {
// submodule
core.info(`Creating tree object for submodule commit at '${path}'`);
return {
path,
mode,
sha: dstSha,
type: 'commit'
};
}
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 chunkedTreeObjects = Array.from({ length: Math.ceil(treeObjects.length / chunkSize) }, (_, i) => treeObjects.slice(i * chunkSize, i * chunkSize + chunkSize));
Expand Down
10 changes: 6 additions & 4 deletions src/git-command-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export type Commit = {
body: string
changes: {
mode: string
dstSha: string
status: 'A' | 'M' | 'D'
path: string
}[]
Expand Down Expand Up @@ -178,13 +179,14 @@ export class GitCommandManager {
body: detailLines.slice(5, endOfBodyIndex).join('\n'),
changes: lines.slice(endOfBodyIndex + 2, -1).map(line => {
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) {
return {
mode: change[3] === 'D' ? change[1] : change[2],
status: change[3],
path: change[4]
mode: change[4] === 'D' ? change[1] : change[2],
dstSha: change[3],
status: change[4],
path: change[5]
}
} else {
unparsedChanges.push(line)
Expand Down
63 changes: 38 additions & 25 deletions src/github-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ type TreeObject = {
path: string
mode: '100644' | '100755' | '040000' | '160000' | '120000'
sha: string | null
type: 'blob'
type: 'blob' | 'commit'
}

export class GitHubHelper {
Expand Down Expand Up @@ -255,31 +255,44 @@ export class GitHubHelper {
if (commit.changes.length > 0) {
core.info(`Creating tree objects for local commit ${commit.sha}`)
const treeObjects = await Promise.all(
commit.changes.map(async ({path, mode, status}) => {
let sha: string | null = null
if (status === 'A' || status === 'M') {
try {
const {data: blob} = await blobCreationLimit(() =>
this.octokit.rest.git.createBlob({
...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
commit.changes.map(async ({path, mode, status, dstSha}) => {
if (mode === '160000') {
// submodule
core.info(`Creating tree object for submodule commit at '${path}'`)
return <TreeObject>{
path,
mode,
sha: dstSha,
type: 'commit'
}
} else {
let sha: string | null = null
if (status === 'A' || status === 'M') {
try {
const {data: blob} = await blobCreationLimit(() =>
this.octokit.rest.git.createBlob({
...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'
}
})
)
Expand Down