Skip to content

Commit

Permalink
Add string[] option to submodules
Browse files Browse the repository at this point in the history
Allows checking out only specific submodules instead of all
  • Loading branch information
Maddimax committed Aug 27, 2024
1 parent 9a9194f commit 03f9a47
Show file tree
Hide file tree
Showing 10 changed files with 128 additions and 22 deletions.
11 changes: 11 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,17 @@ jobs:
submodules: true
- name: Verify submodules true
run: __test__/verify-submodules-true.sh

# Submodules limited
- name: Checkout submodules true
uses: ./
with:
ref: test-data/v2/submodule-ssh-url
path: submodules-true
submodules: true
submodule-directories: submodule-level-1
- name: Verify submodules true
run: __test__/verify-submodules-true.sh

# Submodules recursive
- name: Checkout submodules recursive
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/
# Default: false
submodules: ''

# A list of submodules to use when `submodules` is `true`.
# Default: null
submodule-directories: ''

# Add repository path as safe.directory for Git global config by running `git
# config --global --add safe.directory <path>`
# Default: true
Expand Down
1 change: 1 addition & 0 deletions __test__/git-auth-helper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,7 @@ async function setup(testName: string): Promise<void> {
lfs: false,
submodules: false,
nestedSubmodules: false,
submoduleDirectories: null,
persistCredentials: true,
ref: 'refs/heads/main',
repositoryName: 'my-repo',
Expand Down
17 changes: 17 additions & 0 deletions __test__/input-helper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ describe('input-helper tests', () => {
jest.spyOn(core, 'getInput').mockImplementation((name: string) => {
return inputs[name]
})
// Mock getMultilineInput
jest.spyOn(core, 'getMultilineInput').mockImplementation((name: string) => {
const input: string[] = (inputs[name] || '')
.split('\n')
.filter(x => x !== '')
return input.map(inp => inp.trim())
})

// Mock error/warning/info/debug
jest.spyOn(core, 'error').mockImplementation(jest.fn())
Expand Down Expand Up @@ -87,6 +94,7 @@ describe('input-helper tests', () => {
expect(settings.showProgress).toBe(true)
expect(settings.lfs).toBe(false)
expect(settings.ref).toBe('refs/heads/some-ref')
expect(settings.submoduleDirectories).toBe(null)
expect(settings.repositoryName).toBe('some-repo')
expect(settings.repositoryOwner).toBe('some-owner')
expect(settings.repositoryPath).toBe(gitHubWorkspace)
Expand Down Expand Up @@ -144,4 +152,13 @@ describe('input-helper tests', () => {
const settings: IGitSourceSettings = await inputHelper.getInputs()
expect(settings.workflowOrganizationId).toBe(123456)
})
it('sets submoduleDirectories', async () => {
inputs['submodule-directories'] = 'submodule1\nsubmodule2'
const settings: IGitSourceSettings = await inputHelper.getInputs()
expect(settings.submoduleDirectories).toStrictEqual([
'submodule1',
'submodule2'
])
expect(settings.submodules).toBe(true)
})
})
4 changes: 4 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ inputs:
When the `ssh-key` input is not provided, SSH URLs beginning with `[email protected]:` are
converted to HTTPS.
default: false
submodule-directories:
description: >
A list of submodules to use when `submodules` is `true`.
default: null
set-safe-directory:
description: Add repository path as safe.directory for Git global config by running `git config --global --add safe.directory <path>`
default: true
Expand Down
44 changes: 35 additions & 9 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -795,17 +795,32 @@ class GitCommandManager {
yield this.execGit(args);
});
}
submoduleUpdate(fetchDepth, recursive) {
submoduleUpdate(fetchDepth, recursive, submoduleDirectories) {
return __awaiter(this, void 0, void 0, function* () {
const args = ['-c', 'protocol.version=2'];
args.push('submodule', 'update', '--init', '--force');
if (fetchDepth > 0) {
args.push(`--depth=${fetchDepth}`);
if (submoduleDirectories) {
for (const submodule of submoduleDirectories) {
const args = ['-c', 'protocol.version=2'];
args.push('submodule', 'update', '--init', '--force', submodule);
if (fetchDepth > 0) {
args.push(`--depth=${fetchDepth}`);
}
if (recursive) {
args.push('--recursive');
}
yield this.execGit(args);
}
}
if (recursive) {
args.push('--recursive');
else {
const args = ['-c', 'protocol.version=2'];
args.push('submodule', 'update', '--init', '--force');
if (fetchDepth > 0) {
args.push(`--depth=${fetchDepth}`);
}
if (recursive) {
args.push('--recursive');
}
yield this.execGit(args);
}
yield this.execGit(args);
});
}
submoduleStatus() {
Expand Down Expand Up @@ -1342,7 +1357,7 @@ function getSource(settings) {
// Checkout submodules
core.startGroup('Fetching submodules');
yield git.submoduleSync(settings.nestedSubmodules);
yield git.submoduleUpdate(settings.fetchDepth, settings.nestedSubmodules);
yield git.submoduleUpdate(settings.fetchDepth, settings.nestedSubmodules, settings.submoduleDirectories);
yield git.submoduleForeach('git config --local gc.auto 0', settings.nestedSubmodules);
core.endGroup();
// Persist credentials
Expand Down Expand Up @@ -1805,6 +1820,7 @@ function getInputs() {
// Submodules
result.submodules = false;
result.nestedSubmodules = false;
result.submoduleDirectories = null;
const submodulesString = (core.getInput('submodules') || '').toUpperCase();
if (submodulesString == 'RECURSIVE') {
result.submodules = true;
Expand All @@ -1813,8 +1829,18 @@ function getInputs() {
else if (submodulesString == 'TRUE') {
result.submodules = true;
}
const submoduleDirectories = core.getMultilineInput('submodule-directories');
if (submoduleDirectories.length > 0) {
result.submoduleDirectories = submoduleDirectories;
if (!result.submodules)
result.submodules = true;
}
else {
result.submoduleDirectories = null;
}
core.debug(`submodules = ${result.submodules}`);
core.debug(`recursive submodules = ${result.nestedSubmodules}`);
core.debug(`submodule directories = ${result.submoduleDirectories}`);
// Auth token
result.authToken = core.getInput('token', { required: true });
// SSH
Expand Down
46 changes: 35 additions & 11 deletions src/git-command-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,11 @@ export interface IGitCommandManager {
shaExists(sha: string): Promise<boolean>
submoduleForeach(command: string, recursive: boolean): Promise<string>
submoduleSync(recursive: boolean): Promise<void>
submoduleUpdate(fetchDepth: number, recursive: boolean): Promise<void>
submoduleUpdate(
fetchDepth: number,
recursive: boolean,
submoduleDirectories: string[] | null
): Promise<void>
submoduleStatus(): Promise<boolean>
tagExists(pattern: string): Promise<boolean>
tryClean(): Promise<boolean>
Expand Down Expand Up @@ -409,18 +413,38 @@ class GitCommandManager {
await this.execGit(args)
}

async submoduleUpdate(fetchDepth: number, recursive: boolean): Promise<void> {
const args = ['-c', 'protocol.version=2']
args.push('submodule', 'update', '--init', '--force')
if (fetchDepth > 0) {
args.push(`--depth=${fetchDepth}`)
}
async submoduleUpdate(
fetchDepth: number,
recursive: boolean,
submoduleDirectories: string[] | null
): Promise<void> {
if (submoduleDirectories) {
for (const submodule of submoduleDirectories) {
const args = ['-c', 'protocol.version=2']
args.push('submodule', 'update', '--init', '--force', submodule)
if (fetchDepth > 0) {
args.push(`--depth=${fetchDepth}`)
}

if (recursive) {
args.push('--recursive')
}
if (recursive) {
args.push('--recursive')
}

await this.execGit(args)
await this.execGit(args)
}
} else {
const args = ['-c', 'protocol.version=2']
args.push('submodule', 'update', '--init', '--force')
if (fetchDepth > 0) {
args.push(`--depth=${fetchDepth}`)
}

if (recursive) {
args.push('--recursive')
}

await this.execGit(args)
}
}

async submoduleStatus(): Promise<boolean> {
Expand Down
6 changes: 5 additions & 1 deletion src/git-source-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,11 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
// Checkout submodules
core.startGroup('Fetching submodules')
await git.submoduleSync(settings.nestedSubmodules)
await git.submoduleUpdate(settings.fetchDepth, settings.nestedSubmodules)
await git.submoduleUpdate(
settings.fetchDepth,
settings.nestedSubmodules,
settings.submoduleDirectories
)
await git.submoduleForeach(
'git config --local gc.auto 0',
settings.nestedSubmodules
Expand Down
5 changes: 5 additions & 0 deletions src/git-source-settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ export interface IGitSourceSettings {
*/
nestedSubmodules: boolean

/**
* Indicates which submodule paths to checkout
*/
submoduleDirectories: string[] | null

/**
* The auth token to use when fetching the repository
*/
Expand Down
12 changes: 11 additions & 1 deletion src/input-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,16 +125,26 @@ export async function getInputs(): Promise<IGitSourceSettings> {
// Submodules
result.submodules = false
result.nestedSubmodules = false
result.submoduleDirectories = null
const submodulesString = (core.getInput('submodules') || '').toUpperCase()
if (submodulesString == 'RECURSIVE') {
result.submodules = true
result.nestedSubmodules = true
} else if (submodulesString == 'TRUE') {
result.submodules = true
}

const submoduleDirectories = core.getMultilineInput('submodule-directories')
if (submoduleDirectories.length > 0) {
result.submoduleDirectories = submoduleDirectories
if (!result.submodules) result.submodules = true
} else {
result.submoduleDirectories = null
}

core.debug(`submodules = ${result.submodules}`)
core.debug(`recursive submodules = ${result.nestedSubmodules}`)

core.debug(`submodule directories = ${result.submoduleDirectories}`)
// Auth token
result.authToken = core.getInput('token', {required: true})

Expand Down

0 comments on commit 03f9a47

Please sign in to comment.