Compare commits

...

4 Commits

Author SHA1 Message Date
Marcus Tillmanns
bcf999965a
Merge 7618b1f401 into b684943689 2024-09-05 11:11:04 -07:00
Luca Comellini
b684943689
Add Ref and Commit outputs (#1180)
Signed-off-by: Luca Comellini <luca.com@gmail.com>
2024-09-05 11:57:13 -04:00
Marcus Tillmanns
7618b1f401 Simplified the submoduleDirectories 2024-08-28 13:16:59 +02:00
Marcus Tillmanns
b6625bb44a Add string[] option to submodules
Allows checking out only specific submodules instead of all
2024-08-27 10:37:37 +02:00
11 changed files with 129 additions and 10 deletions

View File

@ -154,6 +154,17 @@ jobs:
submodules: true submodules: true
- name: Verify submodules true - name: Verify submodules true
run: __test__/verify-submodules-true.sh run: __test__/verify-submodules-true.sh
# Submodules limited
- name: Checkout submodules limited
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 # Submodules recursive
- name: Checkout submodules recursive - name: Checkout submodules recursive
@ -295,3 +306,37 @@ jobs:
uses: actions/checkout@v4.1.6 uses: actions/checkout@v4.1.6
with: with:
path: localClone path: localClone
test-output:
runs-on: ubuntu-latest
steps:
# Clone this repo
- name: Checkout
uses: actions/checkout@v4.1.6
# Basic checkout using git
- name: Checkout basic
id: checkout
uses: ./
with:
ref: test-data/v2/basic
# Verify output
- name: Verify output
run: |
echo "Commit: ${{ steps.checkout.outputs.commit }}"
echo "Ref: ${{ steps.checkout.outputs.ref }}"
if [ "${{ steps.checkout.outputs.ref }}" != "test-data/v2/basic" ]; then
echo "Expected ref to be test-data/v2/basic"
exit 1
fi
if [ "${{ steps.checkout.outputs.commit }}" != "82f71901cf8c021332310dcc8cdba84c4193ff5d" ]; then
echo "Expected commit to be 82f71901cf8c021332310dcc8cdba84c4193ff5d"
exit 1
fi
# needed to make checkout post cleanup succeed
- name: Fix Checkout
uses: actions/checkout@v4.1.6

View File

@ -116,6 +116,10 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/
# Default: false # Default: false
submodules: '' submodules: ''
# A list of submodules to checkout.
# Default: null
submodule-directories: ''
# Add repository path as safe.directory for Git global config by running `git # Add repository path as safe.directory for Git global config by running `git
# config --global --add safe.directory <path>` # config --global --add safe.directory <path>`
# Default: true # Default: true

View File

@ -813,6 +813,7 @@ async function setup(testName: string): Promise<void> {
lfs: false, lfs: false,
submodules: false, submodules: false,
nestedSubmodules: false, nestedSubmodules: false,
submoduleDirectories: [],
persistCredentials: true, persistCredentials: true,
ref: 'refs/heads/main', ref: 'refs/heads/main',
repositoryName: 'my-repo', repositoryName: 'my-repo',

View File

@ -21,6 +21,13 @@ describe('input-helper tests', () => {
jest.spyOn(core, 'getInput').mockImplementation((name: string) => { jest.spyOn(core, 'getInput').mockImplementation((name: string) => {
return inputs[name] 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 // Mock error/warning/info/debug
jest.spyOn(core, 'error').mockImplementation(jest.fn()) jest.spyOn(core, 'error').mockImplementation(jest.fn())
@ -87,6 +94,7 @@ describe('input-helper tests', () => {
expect(settings.showProgress).toBe(true) expect(settings.showProgress).toBe(true)
expect(settings.lfs).toBe(false) expect(settings.lfs).toBe(false)
expect(settings.ref).toBe('refs/heads/some-ref') expect(settings.ref).toBe('refs/heads/some-ref')
expect(settings.submoduleDirectories).toStrictEqual([])
expect(settings.repositoryName).toBe('some-repo') expect(settings.repositoryName).toBe('some-repo')
expect(settings.repositoryOwner).toBe('some-owner') expect(settings.repositoryOwner).toBe('some-owner')
expect(settings.repositoryPath).toBe(gitHubWorkspace) expect(settings.repositoryPath).toBe(gitHubWorkspace)
@ -144,4 +152,13 @@ describe('input-helper tests', () => {
const settings: IGitSourceSettings = await inputHelper.getInputs() const settings: IGitSourceSettings = await inputHelper.getInputs()
expect(settings.workflowOrganizationId).toBe(123456) 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)
})
}) })

View File

@ -92,12 +92,21 @@ inputs:
When the `ssh-key` input is not provided, SSH URLs beginning with `git@github.com:` are When the `ssh-key` input is not provided, SSH URLs beginning with `git@github.com:` are
converted to HTTPS. converted to HTTPS.
default: false default: false
submodule-directories:
description: >
A list of submodules to checkout.
default: null
set-safe-directory: set-safe-directory:
description: Add repository path as safe.directory for Git global config by running `git config --global --add safe.directory <path>` description: Add repository path as safe.directory for Git global config by running `git config --global --add safe.directory <path>`
default: true default: true
github-server-url: github-server-url:
description: The base URL for the GitHub instance that you are trying to clone from, will use environment defaults to fetch from the same instance that the workflow is running from unless specified. Example URLs are https://github.com or https://my-ghes-server.example.com description: The base URL for the GitHub instance that you are trying to clone from, will use environment defaults to fetch from the same instance that the workflow is running from unless specified. Example URLs are https://github.com or https://my-ghes-server.example.com
required: false required: false
outputs:
ref:
description: 'The branch, tag or SHA that was checked out'
commit:
description: 'The commit SHA that was checked out'
runs: runs:
using: node20 using: node20
main: dist/index.js main: dist/index.js

18
dist/index.js vendored
View File

@ -795,10 +795,10 @@ class GitCommandManager {
yield this.execGit(args); yield this.execGit(args);
}); });
} }
submoduleUpdate(fetchDepth, recursive) { submoduleUpdate(fetchDepth, recursive, submoduleDirectories) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const args = ['-c', 'protocol.version=2']; const args = ['-c', 'protocol.version=2'];
args.push('submodule', 'update', '--init', '--force'); args.push('submodule', 'update', '--init', '--force', ...submoduleDirectories);
if (fetchDepth > 0) { if (fetchDepth > 0) {
args.push(`--depth=${fetchDepth}`); args.push(`--depth=${fetchDepth}`);
} }
@ -1342,7 +1342,7 @@ function getSource(settings) {
// Checkout submodules // Checkout submodules
core.startGroup('Fetching submodules'); core.startGroup('Fetching submodules');
yield git.submoduleSync(settings.nestedSubmodules); 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); yield git.submoduleForeach('git config --local gc.auto 0', settings.nestedSubmodules);
core.endGroup(); core.endGroup();
// Persist credentials // Persist credentials
@ -1355,7 +1355,8 @@ function getSource(settings) {
// Get commit information // Get commit information
const commitInfo = yield git.log1(); const commitInfo = yield git.log1();
// Log commit sha // Log commit sha
yield git.log1("--format='%H'"); const commitSHA = yield git.log1('--format=%H');
core.setOutput('commit', commitSHA.trim());
// Check for incorrect pull request merge commit // Check for incorrect pull request merge commit
yield refHelper.checkCommitInfo(settings.authToken, commitInfo, settings.repositoryOwner, settings.repositoryName, settings.ref, settings.commit, settings.githubServerUrl); yield refHelper.checkCommitInfo(settings.authToken, commitInfo, settings.repositoryOwner, settings.repositoryName, settings.ref, settings.commit, settings.githubServerUrl);
} }
@ -1805,6 +1806,7 @@ function getInputs() {
// Submodules // Submodules
result.submodules = false; result.submodules = false;
result.nestedSubmodules = false; result.nestedSubmodules = false;
result.submoduleDirectories = [];
const submodulesString = (core.getInput('submodules') || '').toUpperCase(); const submodulesString = (core.getInput('submodules') || '').toUpperCase();
if (submodulesString == 'RECURSIVE') { if (submodulesString == 'RECURSIVE') {
result.submodules = true; result.submodules = true;
@ -1813,8 +1815,15 @@ function getInputs() {
else if (submodulesString == 'TRUE') { else if (submodulesString == 'TRUE') {
result.submodules = true; result.submodules = true;
} }
const submoduleDirectories = core.getMultilineInput('submodule-directories');
if (submoduleDirectories.length > 0) {
result.submoduleDirectories = submoduleDirectories;
if (!result.submodules)
result.submodules = true;
}
core.debug(`submodules = ${result.submodules}`); core.debug(`submodules = ${result.submodules}`);
core.debug(`recursive submodules = ${result.nestedSubmodules}`); core.debug(`recursive submodules = ${result.nestedSubmodules}`);
core.debug(`submodule directories = ${result.submoduleDirectories}`);
// Auth token // Auth token
result.authToken = core.getInput('token', { required: true }); result.authToken = core.getInput('token', { required: true });
// SSH // SSH
@ -1897,6 +1906,7 @@ function run() {
coreCommand.issueCommand('add-matcher', {}, path.join(__dirname, 'problem-matcher.json')); coreCommand.issueCommand('add-matcher', {}, path.join(__dirname, 'problem-matcher.json'));
// Get sources // Get sources
yield gitSourceProvider.getSource(sourceSettings); yield gitSourceProvider.getSource(sourceSettings);
core.setOutput('ref', sourceSettings.ref);
} }
finally { finally {
// Unregister problem matcher // Unregister problem matcher

View File

@ -54,7 +54,11 @@ export interface IGitCommandManager {
shaExists(sha: string): Promise<boolean> shaExists(sha: string): Promise<boolean>
submoduleForeach(command: string, recursive: boolean): Promise<string> submoduleForeach(command: string, recursive: boolean): Promise<string>
submoduleSync(recursive: boolean): Promise<void> submoduleSync(recursive: boolean): Promise<void>
submoduleUpdate(fetchDepth: number, recursive: boolean): Promise<void> submoduleUpdate(
fetchDepth: number,
recursive: boolean,
submoduleDirectories: string[]
): Promise<void>
submoduleStatus(): Promise<boolean> submoduleStatus(): Promise<boolean>
tagExists(pattern: string): Promise<boolean> tagExists(pattern: string): Promise<boolean>
tryClean(): Promise<boolean> tryClean(): Promise<boolean>
@ -409,9 +413,19 @@ class GitCommandManager {
await this.execGit(args) await this.execGit(args)
} }
async submoduleUpdate(fetchDepth: number, recursive: boolean): Promise<void> { async submoduleUpdate(
fetchDepth: number,
recursive: boolean,
submoduleDirectories: string[]
): Promise<void> {
const args = ['-c', 'protocol.version=2'] const args = ['-c', 'protocol.version=2']
args.push('submodule', 'update', '--init', '--force') args.push(
'submodule',
'update',
'--init',
'--force',
...submoduleDirectories
)
if (fetchDepth > 0) { if (fetchDepth > 0) {
args.push(`--depth=${fetchDepth}`) args.push(`--depth=${fetchDepth}`)
} }

View File

@ -242,7 +242,11 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
// Checkout submodules // Checkout submodules
core.startGroup('Fetching submodules') core.startGroup('Fetching submodules')
await git.submoduleSync(settings.nestedSubmodules) await git.submoduleSync(settings.nestedSubmodules)
await git.submoduleUpdate(settings.fetchDepth, settings.nestedSubmodules) await git.submoduleUpdate(
settings.fetchDepth,
settings.nestedSubmodules,
settings.submoduleDirectories
)
await git.submoduleForeach( await git.submoduleForeach(
'git config --local gc.auto 0', 'git config --local gc.auto 0',
settings.nestedSubmodules settings.nestedSubmodules
@ -261,7 +265,8 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
const commitInfo = await git.log1() const commitInfo = await git.log1()
// Log commit sha // Log commit sha
await git.log1("--format='%H'") const commitSHA = await git.log1('--format=%H')
core.setOutput('commit', commitSHA.trim())
// Check for incorrect pull request merge commit // Check for incorrect pull request merge commit
await refHelper.checkCommitInfo( await refHelper.checkCommitInfo(

View File

@ -74,6 +74,11 @@ export interface IGitSourceSettings {
*/ */
nestedSubmodules: boolean nestedSubmodules: boolean
/**
* Indicates which submodule paths to checkout
*/
submoduleDirectories: string[]
/** /**
* The auth token to use when fetching the repository * The auth token to use when fetching the repository
*/ */

View File

@ -125,6 +125,7 @@ export async function getInputs(): Promise<IGitSourceSettings> {
// Submodules // Submodules
result.submodules = false result.submodules = false
result.nestedSubmodules = false result.nestedSubmodules = false
result.submoduleDirectories = []
const submodulesString = (core.getInput('submodules') || '').toUpperCase() const submodulesString = (core.getInput('submodules') || '').toUpperCase()
if (submodulesString == 'RECURSIVE') { if (submodulesString == 'RECURSIVE') {
result.submodules = true result.submodules = true
@ -132,9 +133,16 @@ export async function getInputs(): Promise<IGitSourceSettings> {
} else if (submodulesString == 'TRUE') { } else if (submodulesString == 'TRUE') {
result.submodules = true result.submodules = true
} }
const submoduleDirectories = core.getMultilineInput('submodule-directories')
if (submoduleDirectories.length > 0) {
result.submoduleDirectories = submoduleDirectories
if (!result.submodules) result.submodules = true
}
core.debug(`submodules = ${result.submodules}`) core.debug(`submodules = ${result.submodules}`)
core.debug(`recursive submodules = ${result.nestedSubmodules}`) core.debug(`recursive submodules = ${result.nestedSubmodules}`)
core.debug(`submodule directories = ${result.submoduleDirectories}`)
// Auth token // Auth token
result.authToken = core.getInput('token', {required: true}) result.authToken = core.getInput('token', {required: true})

View File

@ -19,6 +19,7 @@ async function run(): Promise<void> {
// Get sources // Get sources
await gitSourceProvider.getSource(sourceSettings) await gitSourceProvider.getSource(sourceSettings)
core.setOutput('ref', sourceSettings.ref)
} finally { } finally {
// Unregister problem matcher // Unregister problem matcher
coreCommand.issueCommand('remove-matcher', {owner: 'checkout-git'}, '') coreCommand.issueCommand('remove-matcher', {owner: 'checkout-git'}, '')