1
0
mirror of https://github.com/actions/checkout.git synced 2026-07-08 19:03:47 +08:00

Compare commits

...

12 Commits

Author SHA1 Message Date
Steven Van Ingelgem
09983f9bdf Merge 0548471950 into 8edcb1bdb4 2025-07-23 17:02:18 +03:00
Tingluo Huang
8edcb1bdb4 Update CODEOWNERS for actions (#2224) 2025-07-23 09:20:20 -04:00
Steven Van Ingelgem
0548471950 Updated tests for the differences in 2.48 behaviour 2025-06-10 09:26:54 +02:00
Steven Van Ingelgem
49528c1b57 Proper 2.48 tags handling 2025-06-10 09:24:51 +02:00
Steven Van Ingelgem
f3e6cc288d Ignore intellij 2025-06-10 09:24:38 +02:00
Steven Van Ingelgem
6b47c9436e Allow to fetch tags. 2025-06-10 08:45:30 +02:00
Steven Van Ingelgem
df9ce67227 Allow to fetch tags. 2025-06-10 08:37:42 +02:00
Ben De St Paer-Gotch
09d2acae67 Update README.md (#2194) 2025-06-06 09:19:16 +01:00
Josh Gross
85e6279cec Adjust positioning of user email note and permissions heading (#2044) 2025-01-16 15:56:18 -05:00
Ben Wells
009b9ae9e4 Documentation update - add recommended permissions to Readme (#2043)
* Update README.md

* Update README.md

Co-authored-by: Josh Gross <joshmgross@github.com>

---------

Co-authored-by: Josh Gross <joshmgross@github.com>
2025-01-16 14:14:48 -05:00
Mohammad Ismail
cbb722410c Update README.md (#1977) 2024-11-14 10:41:00 -05:00
The web walker
3b9b8c884f docs: update README.md (#1971)
Add a scenario where it is necessary to push a commit to a pull request.
2024-11-08 10:32:54 -05:00
6 changed files with 304 additions and 8 deletions

3
.gitignore vendored
View File

@@ -2,4 +2,5 @@ __test__/_temp
_temp/
lib/
node_modules/
.vscode/
.vscode/
.idea/

View File

@@ -1 +1 @@
* @actions/actions-launch
* @actions/actions-runtime

View File

@@ -10,6 +10,24 @@ The auth token is persisted in the local git config. This enables your scripts t
When Git 2.18 or higher is not in your PATH, falls back to the REST API to download the files.
### Note
Thank you for your interest in this GitHub action, however, right now we are not taking contributions.
We continue to focus our resources on strategic areas that help our customers be successful while making developers' lives easier. While GitHub Actions remains a key part of this vision, we are allocating resources towards other areas of Actions and are not taking contributions to this repository at this time. The GitHub public roadmap is the best place to follow along for any updates on features were working on and what stage theyre in.
We are taking the following steps to better direct requests related to GitHub Actions, including:
1. We will be directing questions and support requests to our [Community Discussions area](https://github.com/orgs/community/discussions/categories/actions)
2. High Priority bugs can be reported through Community Discussions or you can report these to our support team https://support.github.com/contact/bug-report.
3. Security Issues should be handled as per our [security.md](security.md)
We will still provide security updates for this project and fix major breaking changes during this time.
You are welcome to still raise bugs in this repo.
# What's new
Please refer to the [release page](https://github.com/actions/checkout/releases/latest) for the latest release notes.
@@ -143,6 +161,7 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/
- [Checkout pull request HEAD commit instead of merge commit](#Checkout-pull-request-HEAD-commit-instead-of-merge-commit)
- [Checkout pull request on closed event](#Checkout-pull-request-on-closed-event)
- [Push a commit using the built-in token](#Push-a-commit-using-the-built-in-token)
- [Push a commit to a PR using the built-in token](#Push-a-commit-to-a-PR-using-the-built-in-token)
## Fetch only the root files
@@ -211,7 +230,7 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/
repository: my-org/my-tools
path: my-tools
```
> - If your secondary repository is private you will need to add the option noted in [Checkout multiple repos (private)](#Checkout-multiple-repos-private)
> - If your secondary repository is private or internal you will need to add the option noted in [Checkout multiple repos (private)](#Checkout-multiple-repos-private)
## Checkout multiple repos (nested)
@@ -225,7 +244,7 @@ Please refer to the [release page](https://github.com/actions/checkout/releases/
repository: my-org/my-tools
path: my-tools
```
> - If your secondary repository is private you will need to add the option noted in [Checkout multiple repos (private)](#Checkout-multiple-repos-private)
> - If your secondary repository is private or internal you will need to add the option noted in [Checkout multiple repos (private)](#Checkout-multiple-repos-private)
## Checkout multiple repos (private)
@@ -288,6 +307,40 @@ jobs:
```
*NOTE:* The user email is `{user.id}+{user.login}@users.noreply.github.com`. See users API: https://api.github.com/users/github-actions%5Bbot%5D
## Push a commit to a PR using the built-in token
In a pull request trigger, `ref` is required as GitHub Actions checks out in detached HEAD mode, meaning it doesnt check out your branch by default.
```yaml
on: pull_request
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.head_ref }}
- run: |
date > generated.txt
# Note: the following account information will not work on GHES
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add .
git commit -m "generated"
git push
```
*NOTE:* The user email is `{user.id}+{user.login}@users.noreply.github.com`. See users API: https://api.github.com/users/github-actions%5Bbot%5D
# Recommended permissions
When using the `checkout` action in your GitHub Actions workflow, it is recommended to set the following `GITHUB_TOKEN` permissions to ensure proper functionality, unless alternative auth is provided via the `token` or `ssh-key` inputs:
```yaml
permissions:
contents: read
```
# License
The scripts and documentation in this project are released under the [MIT License](LICENSE)

View File

@@ -134,6 +134,7 @@ describe('Test fetchDepth and fetchTags options', () => {
'-c',
'protocol.version=2',
'fetch',
'--tags',
'--prune',
'--no-recurse-submodules',
'--filter=filterValue',
@@ -248,6 +249,7 @@ describe('Test fetchDepth and fetchTags options', () => {
'-c',
'protocol.version=2',
'fetch',
'--tags',
'--prune',
'--no-recurse-submodules',
'--filter=filterValue',
@@ -364,6 +366,7 @@ describe('Test fetchDepth and fetchTags options', () => {
'-c',
'protocol.version=2',
'fetch',
'--tags',
'--prune',
'--no-recurse-submodules',
'--progress',
@@ -376,3 +379,225 @@ describe('Test fetchDepth and fetchTags options', () => {
)
})
})
describe('Test git 2.48 tag fetching behavior', () => {
beforeEach(async () => {
jest.spyOn(fshelper, 'fileExistsSync').mockImplementation(jest.fn())
jest.spyOn(fshelper, 'directoryExistsSync').mockImplementation(jest.fn())
})
afterEach(() => {
jest.restoreAllMocks()
})
it('should perform separate tag fetch for git 2.48 when fetchTags is true', async () => {
mockExec.mockImplementation((path, args, options) => {
if (args.includes('version')) {
options.listeners.stdout(Buffer.from('2.48.1'))
}
return 0
})
jest.spyOn(exec, 'exec').mockImplementation(mockExec)
const workingDirectory = 'test'
const lfs = false
const doSparseCheckout = false
git = await commandManager.createCommandManager(
workingDirectory,
lfs,
doSparseCheckout
)
const refSpec = ['refspec1']
const options = {
fetchTags: true
}
await git.fetch(refSpec, options)
// First call: main fetch with --no-tags
expect(mockExec).toHaveBeenNthCalledWith(
2, // First call is version check
expect.any(String),
[
'-c',
'protocol.version=2',
'fetch',
'--no-tags',
'--prune',
'--no-recurse-submodules',
'origin',
'refspec1'
],
expect.any(Object)
)
// Second call: separate tag fetch
expect(mockExec).toHaveBeenNthCalledWith(
3,
expect.any(String),
[
'-c',
'protocol.version=2',
'fetch',
'--tags',
'--prune',
'origin'
],
expect.any(Object)
)
expect(mockExec).toHaveBeenCalledTimes(3) // version + main fetch + tag fetch
})
it('should perform separate tag fetch with progress for git 2.48', async () => {
mockExec.mockImplementation((path, args, options) => {
if (args.includes('version')) {
options.listeners.stdout(Buffer.from('2.48.0'))
}
return 0
})
jest.spyOn(exec, 'exec').mockImplementation(mockExec)
const workingDirectory = 'test'
const lfs = false
const doSparseCheckout = false
git = await commandManager.createCommandManager(
workingDirectory,
lfs,
doSparseCheckout
)
const refSpec = ['refspec1']
const options = {
fetchTags: true,
showProgress: true
}
await git.fetch(refSpec, options)
// Main fetch with --no-tags and --progress
expect(mockExec).toHaveBeenNthCalledWith(
2,
expect.any(String),
[
'-c',
'protocol.version=2',
'fetch',
'--no-tags',
'--prune',
'--no-recurse-submodules',
'--progress',
'origin',
'refspec1'
],
expect.any(Object)
)
// Separate tag fetch with --progress
expect(mockExec).toHaveBeenNthCalledWith(
3,
expect.any(String),
[
'-c',
'protocol.version=2',
'fetch',
'--tags',
'--prune',
'--progress',
'origin'
],
expect.any(Object)
)
})
it('should NOT perform separate tag fetch for git 2.48 when fetchTags is false', async () => {
mockExec.mockImplementation((path, args, options) => {
if (args.includes('version')) {
options.listeners.stdout(Buffer.from('2.48.1'))
}
return 0
})
jest.spyOn(exec, 'exec').mockImplementation(mockExec)
const workingDirectory = 'test'
const lfs = false
const doSparseCheckout = false
git = await commandManager.createCommandManager(
workingDirectory,
lfs,
doSparseCheckout
)
const refSpec = ['refspec1']
const options = {
fetchTags: false
}
await git.fetch(refSpec, options)
// Only one fetch call with --no-tags
expect(mockExec).toHaveBeenNthCalledWith(
2,
expect.any(String),
[
'-c',
'protocol.version=2',
'fetch',
'--no-tags',
'--prune',
'--no-recurse-submodules',
'origin',
'refspec1'
],
expect.any(Object)
)
expect(mockExec).toHaveBeenCalledTimes(2) // version + single fetch only
})
it('should use normal behavior for non-2.48 git versions', async () => {
mockExec.mockImplementation((path, args, options) => {
if (args.includes('version')) {
options.listeners.stdout(Buffer.from('2.47.0'))
}
return 0
})
jest.spyOn(exec, 'exec').mockImplementation(mockExec)
const workingDirectory = 'test'
const lfs = false
const doSparseCheckout = false
git = await commandManager.createCommandManager(
workingDirectory,
lfs,
doSparseCheckout
)
const refSpec = ['refspec1']
const options = {
fetchTags: true
}
await git.fetch(refSpec, options)
// Single fetch with --tags
expect(mockExec).toHaveBeenNthCalledWith(
2,
expect.any(String),
[
'-c',
'protocol.version=2',
'fetch',
'--tags',
'--prune',
'--no-recurse-submodules',
'origin',
'refspec1'
],
expect.any(Object)
)
expect(mockExec).toHaveBeenCalledTimes(2) // version + single fetch only
})
})

4
dist/index.js vendored
View File

@@ -653,8 +653,8 @@ class GitCommandManager {
fetch(refSpec, options) {
return __awaiter(this, void 0, void 0, function* () {
const args = ['-c', 'protocol.version=2', 'fetch'];
if (!refSpec.some(x => x === refHelper.tagsRefSpec) && !options.fetchTags) {
args.push('--no-tags');
if (!refSpec.some(x => x === refHelper.tagsRefSpec)) {
args.push(options.fetchTags ? '--tags' : '--no-tags');
}
args.push('--prune', '--no-recurse-submodules');
if (options.showProgress) {

View File

@@ -261,8 +261,12 @@ class GitCommandManager {
}
): Promise<void> {
const args = ['-c', 'protocol.version=2', 'fetch']
if (!refSpec.some(x => x === refHelper.tagsRefSpec) && !options.fetchTags) {
args.push('--no-tags')
const hasTagsRefSpec = refSpec.some(x => x === refHelper.tagsRefSpec)
const needsSeparateTagFetch = this.gitVersion.toString().startsWith('2.48') && options.fetchTags && !hasTagsRefSpec
if (!hasTagsRefSpec) {
// For git 2.48, skip --tags here if we need separate fetch
args.push(needsSeparateTagFetch || !options.fetchTags ? '--no-tags' : '--tags')
}
args.push('--prune', '--no-recurse-submodules')
@@ -293,6 +297,19 @@ class GitCommandManager {
await retryHelper.execute(async () => {
await that.execGit(args)
})
// Separate tag fetch for git 2.48
if (needsSeparateTagFetch) {
const tagArgs = ['-c', 'protocol.version=2', 'fetch', '--tags', '--prune']
if (options.showProgress) {
tagArgs.push('--progress')
}
tagArgs.push('origin')
await retryHelper.execute(async () => {
await that.execGit(tagArgs)
})
}
}
async getDefaultBranch(repositoryUrl: string): Promise<string> {