Skip to content

Commit 47fbe2d

Browse files
megamanicsLink-sminnie
authored
Fix: Checkout fail in self-hosted runners when faulty submodule are checked-in (#1196)
* Fix Self hosted runner issue wrt bad submodules - solution cleanup working space. * Fix format with npm run format output * Add mock implementation for new function submoduleStatus * Add 2 test cases for submodule status. * Codeql-Action Analyse revert v1 to v2 --------- Co-authored-by: Bassem Dghaidi <[email protected]> Co-authored-by: sminnie <[email protected]>
1 parent 8e5e7e5 commit 47fbe2d

5 files changed

+90
-0
lines changed

__test__/git-auth-helper.test.ts

+3
Original file line numberDiff line numberDiff line change
@@ -770,6 +770,9 @@ async function setup(testName: string): Promise<void> {
770770
return ''
771771
}),
772772
submoduleSync: jest.fn(),
773+
submoduleStatus: jest.fn(async () => {
774+
return true
775+
}),
773776
submoduleUpdate: jest.fn(),
774777
tagExists: jest.fn(),
775778
tryClean: jest.fn(),

__test__/git-directory-helper.test.ts

+62
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,65 @@ describe('git-directory-helper tests', () => {
281281
expect(git.branchDelete).toHaveBeenCalledWith(false, 'local-branch-2')
282282
})
283283

284+
const cleanWhenSubmoduleStatusIsFalse =
285+
'cleans when submodule status is false'
286+
287+
it(cleanWhenSubmoduleStatusIsFalse, async () => {
288+
// Arrange
289+
await setup(cleanWhenSubmoduleStatusIsFalse)
290+
await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '')
291+
292+
//mock bad submodule
293+
294+
const submoduleStatus = git.submoduleStatus as jest.Mock<any, any>
295+
submoduleStatus.mockImplementation(async (remote: boolean) => {
296+
return false
297+
})
298+
299+
// Act
300+
await gitDirectoryHelper.prepareExistingDirectory(
301+
git,
302+
repositoryPath,
303+
repositoryUrl,
304+
clean,
305+
ref
306+
)
307+
308+
// Assert
309+
const files = await fs.promises.readdir(repositoryPath)
310+
expect(files).toHaveLength(0)
311+
expect(git.tryClean).toHaveBeenCalled()
312+
})
313+
314+
const doesNotCleanWhenSubmoduleStatusIsTrue =
315+
'does not clean when submodule status is true'
316+
317+
it(doesNotCleanWhenSubmoduleStatusIsTrue, async () => {
318+
// Arrange
319+
await setup(doesNotCleanWhenSubmoduleStatusIsTrue)
320+
await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '')
321+
322+
const submoduleStatus = git.submoduleStatus as jest.Mock<any, any>
323+
submoduleStatus.mockImplementation(async (remote: boolean) => {
324+
return true
325+
})
326+
327+
// Act
328+
await gitDirectoryHelper.prepareExistingDirectory(
329+
git,
330+
repositoryPath,
331+
repositoryUrl,
332+
clean,
333+
ref
334+
)
335+
336+
// Assert
337+
338+
const files = await fs.promises.readdir(repositoryPath)
339+
expect(files.sort()).toEqual(['.git', 'my-file'])
340+
expect(git.tryClean).toHaveBeenCalled()
341+
})
342+
284343
const removesLockFiles = 'removes lock files'
285344
it(removesLockFiles, async () => {
286345
// Arrange
@@ -423,6 +482,9 @@ async function setup(testName: string): Promise<void> {
423482
submoduleForeach: jest.fn(),
424483
submoduleSync: jest.fn(),
425484
submoduleUpdate: jest.fn(),
485+
submoduleStatus: jest.fn(async () => {
486+
return true
487+
}),
426488
tagExists: jest.fn(),
427489
tryClean: jest.fn(async () => {
428490
return true

dist/index.js

+12
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,13 @@ class GitCommandManager {
765765
yield this.execGit(args);
766766
});
767767
}
768+
submoduleStatus() {
769+
return __awaiter(this, void 0, void 0, function* () {
770+
const output = yield this.execGit(['submodule', 'status'], true);
771+
core.debug(output.stdout);
772+
return output.exitCode === 0;
773+
});
774+
}
768775
tagExists(pattern) {
769776
return __awaiter(this, void 0, void 0, function* () {
770777
const output = yield this.execGit(['tag', '--list', pattern]);
@@ -1023,6 +1030,11 @@ function prepareExistingDirectory(git, repositoryPath, repositoryUrl, clean, ref
10231030
}
10241031
}
10251032
core.endGroup();
1033+
// Check for submodules and delete any existing files if submodules are present
1034+
if (!(yield git.submoduleStatus())) {
1035+
remove = true;
1036+
core.info('Bad Submodules found, removing existing files');
1037+
}
10261038
// Clean
10271039
if (clean) {
10281040
core.startGroup('Cleaning the repository');

src/git-command-manager.ts

+7
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export interface IGitCommandManager {
4141
submoduleForeach(command: string, recursive: boolean): Promise<string>
4242
submoduleSync(recursive: boolean): Promise<void>
4343
submoduleUpdate(fetchDepth: number, recursive: boolean): Promise<void>
44+
submoduleStatus(): Promise<boolean>
4445
tagExists(pattern: string): Promise<boolean>
4546
tryClean(): Promise<boolean>
4647
tryConfigUnset(configKey: string, globalConfig?: boolean): Promise<boolean>
@@ -357,6 +358,12 @@ class GitCommandManager {
357358
await this.execGit(args)
358359
}
359360

361+
async submoduleStatus(): Promise<boolean> {
362+
const output = await this.execGit(['submodule', 'status'], true)
363+
core.debug(output.stdout)
364+
return output.exitCode === 0
365+
}
366+
360367
async tagExists(pattern: string): Promise<boolean> {
361368
const output = await this.execGit(['tag', '--list', pattern])
362369
return !!output.stdout.trim()

src/git-directory-helper.ts

+6
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ export async function prepareExistingDirectory(
8181
}
8282
core.endGroup()
8383

84+
// Check for submodules and delete any existing files if submodules are present
85+
if (!(await git.submoduleStatus())) {
86+
remove = true
87+
core.info('Bad Submodules found, removing existing files')
88+
}
89+
8490
// Clean
8591
if (clean) {
8692
core.startGroup('Cleaning the repository')

0 commit comments

Comments
 (0)