mirror of
https://github.com/actions/checkout.git
synced 2025-07-13 12:13:51 +00:00
Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
c85c95e3d7 | |||
d106d4669b | |||
f095bcc56b | |||
47fbe2df0a | |||
8e5e7e5ab8 | |||
eb35239ec2 | |||
83b7061638 | |||
40a16ebeed | |||
8f4b7f8486 | |||
cd6a9fd493 |
27
.github/workflows/test.yml
vendored
27
.github/workflows/test.yml
vendored
@ -72,6 +72,33 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: __test__/verify-side-by-side.sh
|
run: __test__/verify-side-by-side.sh
|
||||||
|
|
||||||
|
# Sparse checkout
|
||||||
|
- name: Sparse checkout
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
sparse-checkout: |
|
||||||
|
__test__
|
||||||
|
.github
|
||||||
|
dist
|
||||||
|
path: sparse-checkout
|
||||||
|
|
||||||
|
- name: Verify sparse checkout
|
||||||
|
run: __test__/verify-sparse-checkout.sh
|
||||||
|
|
||||||
|
# Sparse checkout (non-cone mode)
|
||||||
|
- name: Sparse checkout (non-cone mode)
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
sparse-checkout: |
|
||||||
|
/__test__/
|
||||||
|
/.github/
|
||||||
|
/dist/
|
||||||
|
sparse-checkout-cone-mode: false
|
||||||
|
path: sparse-checkout-non-cone-mode
|
||||||
|
|
||||||
|
- name: Verify sparse checkout (non-cone mode)
|
||||||
|
run: __test__/verify-sparse-checkout-non-cone-mode.sh
|
||||||
|
|
||||||
# LFS
|
# LFS
|
||||||
- name: Checkout LFS
|
- name: Checkout LFS
|
||||||
uses: ./
|
uses: ./
|
||||||
|
11
.github/workflows/update-main-version.yml
vendored
11
.github/workflows/update-main-version.yml
vendored
@ -1,5 +1,5 @@
|
|||||||
name: Update Main Version
|
name: Update Main Version
|
||||||
run-name: Move ${{ github.event.inputs.main_version }} to ${{ github.event.inputs.target }}
|
run-name: Move ${{ github.event.inputs.major_version }} to ${{ github.event.inputs.target }}
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
@ -7,11 +7,12 @@ on:
|
|||||||
target:
|
target:
|
||||||
description: The tag or reference to use
|
description: The tag or reference to use
|
||||||
required: true
|
required: true
|
||||||
main_version:
|
major_version:
|
||||||
type: choice
|
type: choice
|
||||||
description: The main version to update
|
description: The major version to update
|
||||||
options:
|
options:
|
||||||
- v3
|
- v3
|
||||||
|
- v2
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
tag:
|
tag:
|
||||||
@ -25,6 +26,6 @@ jobs:
|
|||||||
git config user.name github-actions
|
git config user.name github-actions
|
||||||
git config user.email github-actions@github.com
|
git config user.email github-actions@github.com
|
||||||
- name: Tag new target
|
- name: Tag new target
|
||||||
run: git tag -f ${{ github.event.inputs.main_version }} ${{ github.event.inputs.target }}
|
run: git tag -f ${{ github.event.inputs.major_version }} ${{ github.event.inputs.target }}
|
||||||
- name: Push new tag
|
- name: Push new tag
|
||||||
run: git push origin ${{ github.event.inputs.main_version }} --force
|
run: git push origin ${{ github.event.inputs.major_version }} --force
|
||||||
|
BIN
.licenses/npm/@actions/github.dep.yml
generated
BIN
.licenses/npm/@actions/github.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@actions/http-client-1.0.8.dep.yml
generated
BIN
.licenses/npm/@actions/http-client-1.0.8.dep.yml
generated
Binary file not shown.
Binary file not shown.
BIN
.licenses/npm/@octokit/auth-token.dep.yml
generated
BIN
.licenses/npm/@octokit/auth-token.dep.yml
generated
Binary file not shown.
Binary file not shown.
BIN
.licenses/npm/@octokit/endpoint.dep.yml
generated
BIN
.licenses/npm/@octokit/endpoint.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@octokit/graphql.dep.yml
generated
BIN
.licenses/npm/@octokit/graphql.dep.yml
generated
Binary file not shown.
Binary file not shown.
BIN
.licenses/npm/@octokit/plugin-paginate-rest.dep.yml
generated
BIN
.licenses/npm/@octokit/plugin-paginate-rest.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@octokit/plugin-request-log.dep.yml
generated
BIN
.licenses/npm/@octokit/plugin-request-log.dep.yml
generated
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.licenses/npm/@octokit/request.dep.yml
generated
BIN
.licenses/npm/@octokit/request.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@octokit/rest.dep.yml
generated
BIN
.licenses/npm/@octokit/rest.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@octokit/types.dep.yml
generated
BIN
.licenses/npm/@octokit/types.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/@types/node.dep.yml
generated
BIN
.licenses/npm/@types/node.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/atob-lite.dep.yml
generated
BIN
.licenses/npm/atob-lite.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/before-after-hook.dep.yml
generated
BIN
.licenses/npm/before-after-hook.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/btoa-lite.dep.yml
generated
BIN
.licenses/npm/btoa-lite.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/cross-spawn.dep.yml
generated
BIN
.licenses/npm/cross-spawn.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/end-of-stream.dep.yml
generated
BIN
.licenses/npm/end-of-stream.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/get-stream.dep.yml
generated
BIN
.licenses/npm/get-stream.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/is-plain-object.dep.yml
generated
BIN
.licenses/npm/is-plain-object.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/is-stream.dep.yml
generated
BIN
.licenses/npm/is-stream.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/isexe.dep.yml
generated
BIN
.licenses/npm/isexe.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/isobject.dep.yml
generated
BIN
.licenses/npm/isobject.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/lodash.get.dep.yml
generated
BIN
.licenses/npm/lodash.get.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/lodash.set.dep.yml
generated
BIN
.licenses/npm/lodash.set.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/lodash.uniq.dep.yml
generated
BIN
.licenses/npm/lodash.uniq.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/macos-release.dep.yml
generated
BIN
.licenses/npm/macos-release.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/nice-try.dep.yml
generated
BIN
.licenses/npm/nice-try.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/node-fetch.dep.yml
generated
BIN
.licenses/npm/node-fetch.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/npm-run-path.dep.yml
generated
BIN
.licenses/npm/npm-run-path.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/octokit-pagination-methods.dep.yml
generated
BIN
.licenses/npm/octokit-pagination-methods.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/os-name.dep.yml
generated
BIN
.licenses/npm/os-name.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/p-finally.dep.yml
generated
BIN
.licenses/npm/p-finally.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/path-key.dep.yml
generated
BIN
.licenses/npm/path-key.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/pump.dep.yml
generated
BIN
.licenses/npm/pump.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/semver-5.7.1.dep.yml
generated
BIN
.licenses/npm/semver-5.7.1.dep.yml
generated
Binary file not shown.
Binary file not shown.
BIN
.licenses/npm/shebang-command.dep.yml
generated
BIN
.licenses/npm/shebang-command.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/shebang-regex.dep.yml
generated
BIN
.licenses/npm/shebang-regex.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/signal-exit.dep.yml
generated
BIN
.licenses/npm/signal-exit.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/strip-eof.dep.yml
generated
BIN
.licenses/npm/strip-eof.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/universal-user-agent-5.0.0.dep.yml
generated
BIN
.licenses/npm/universal-user-agent-5.0.0.dep.yml
generated
Binary file not shown.
Binary file not shown.
BIN
.licenses/npm/which.dep.yml
generated
BIN
.licenses/npm/which.dep.yml
generated
Binary file not shown.
BIN
.licenses/npm/windows-release.dep.yml
generated
BIN
.licenses/npm/windows-release.dep.yml
generated
Binary file not shown.
14
CHANGELOG.md
14
CHANGELOG.md
@ -1,5 +1,19 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v3.5.3
|
||||||
|
- [Fix: Checkout fail in self-hosted runners when faulty submodule are checked-in](https://github.com/actions/checkout/pull/1196)
|
||||||
|
- [Fix typos found by codespell](https://github.com/actions/checkout/pull/1287)
|
||||||
|
- [Add support for sparse checkouts](https://github.com/actions/checkout/pull/1369)
|
||||||
|
|
||||||
|
## v3.5.2
|
||||||
|
- [Fix api endpoint for GHES](https://github.com/actions/checkout/pull/1289)
|
||||||
|
|
||||||
|
## v3.5.1
|
||||||
|
- [Fix slow checkout on Windows](https://github.com/actions/checkout/pull/1246)
|
||||||
|
|
||||||
|
## v3.5.0
|
||||||
|
* [Add new public key for known_hosts](https://github.com/actions/checkout/pull/1237)
|
||||||
|
|
||||||
## v3.4.0
|
## v3.4.0
|
||||||
- [Upgrade codeql actions to v2](https://github.com/actions/checkout/pull/1209)
|
- [Upgrade codeql actions to v2](https://github.com/actions/checkout/pull/1209)
|
||||||
- [Upgrade dependencies](https://github.com/actions/checkout/pull/1210)
|
- [Upgrade dependencies](https://github.com/actions/checkout/pull/1210)
|
||||||
|
40
README.md
40
README.md
@ -74,6 +74,15 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
|
|||||||
# Default: true
|
# Default: true
|
||||||
clean: ''
|
clean: ''
|
||||||
|
|
||||||
|
# Do a sparse checkout on given patterns. Each pattern should be separated with
|
||||||
|
# new lines
|
||||||
|
# Default: null
|
||||||
|
sparse-checkout: ''
|
||||||
|
|
||||||
|
# Specifies whether to use cone-mode when doing a sparse checkout.
|
||||||
|
# Default: true
|
||||||
|
sparse-checkout-cone-mode: ''
|
||||||
|
|
||||||
# Number of commits to fetch. 0 indicates all history for all branches and tags.
|
# Number of commits to fetch. 0 indicates all history for all branches and tags.
|
||||||
# Default: 1
|
# Default: 1
|
||||||
fetch-depth: ''
|
fetch-depth: ''
|
||||||
@ -106,6 +115,9 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
|
|||||||
|
|
||||||
# Scenarios
|
# Scenarios
|
||||||
|
|
||||||
|
- [Fetch only the root files](#Fetch-only-the-root-files)
|
||||||
|
- [Fetch only the root files and `.github` and `src` folder](#Fetch-only-the-root-files-and-github-and-src-folder)
|
||||||
|
- [Fetch only a single file](#Fetch-only-a-single-file)
|
||||||
- [Fetch all history for all tags and branches](#Fetch-all-history-for-all-tags-and-branches)
|
- [Fetch all history for all tags and branches](#Fetch-all-history-for-all-tags-and-branches)
|
||||||
- [Checkout a different branch](#Checkout-a-different-branch)
|
- [Checkout a different branch](#Checkout-a-different-branch)
|
||||||
- [Checkout HEAD^](#Checkout-HEAD)
|
- [Checkout HEAD^](#Checkout-HEAD)
|
||||||
@ -116,6 +128,34 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
|
|||||||
- [Checkout pull request on closed event](#Checkout-pull-request-on-closed-event)
|
- [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 using the built-in token](#Push-a-commit-using-the-built-in-token)
|
||||||
|
|
||||||
|
## Fetch only the root files
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
sparse-checkout: .
|
||||||
|
```
|
||||||
|
|
||||||
|
## Fetch only the root files and `.github` and `src` folder
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
sparse-checkout: |
|
||||||
|
.github
|
||||||
|
src
|
||||||
|
```
|
||||||
|
|
||||||
|
## Fetch only a single file
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
sparse-checkout: |
|
||||||
|
README.md
|
||||||
|
sparse-checkout-cone-mode: false
|
||||||
|
```
|
||||||
|
|
||||||
## Fetch all history for all tags and branches
|
## Fetch all history for all tags and branches
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
|
@ -727,6 +727,8 @@ async function setup(testName: string): Promise<void> {
|
|||||||
branchDelete: jest.fn(),
|
branchDelete: jest.fn(),
|
||||||
branchExists: jest.fn(),
|
branchExists: jest.fn(),
|
||||||
branchList: jest.fn(),
|
branchList: jest.fn(),
|
||||||
|
sparseCheckout: jest.fn(),
|
||||||
|
sparseCheckoutNonConeMode: jest.fn(),
|
||||||
checkout: jest.fn(),
|
checkout: jest.fn(),
|
||||||
checkoutDetach: jest.fn(),
|
checkoutDetach: jest.fn(),
|
||||||
config: jest.fn(
|
config: jest.fn(
|
||||||
@ -770,6 +772,9 @@ async function setup(testName: string): Promise<void> {
|
|||||||
return ''
|
return ''
|
||||||
}),
|
}),
|
||||||
submoduleSync: jest.fn(),
|
submoduleSync: jest.fn(),
|
||||||
|
submoduleStatus: jest.fn(async () => {
|
||||||
|
return true
|
||||||
|
}),
|
||||||
submoduleUpdate: jest.fn(),
|
submoduleUpdate: jest.fn(),
|
||||||
tagExists: jest.fn(),
|
tagExists: jest.fn(),
|
||||||
tryClean: jest.fn(),
|
tryClean: jest.fn(),
|
||||||
@ -797,6 +802,8 @@ async function setup(testName: string): Promise<void> {
|
|||||||
authToken: 'some auth token',
|
authToken: 'some auth token',
|
||||||
clean: true,
|
clean: true,
|
||||||
commit: '',
|
commit: '',
|
||||||
|
sparseCheckout: [],
|
||||||
|
sparseCheckoutConeMode: true,
|
||||||
fetchDepth: 1,
|
fetchDepth: 1,
|
||||||
lfs: false,
|
lfs: false,
|
||||||
submodules: false,
|
submodules: false,
|
||||||
|
@ -39,7 +39,12 @@ describe('git-auth-helper tests', () => {
|
|||||||
jest.spyOn(exec, 'exec').mockImplementation(mockExec)
|
jest.spyOn(exec, 'exec').mockImplementation(mockExec)
|
||||||
const workingDirectory = 'test'
|
const workingDirectory = 'test'
|
||||||
const lfs = false
|
const lfs = false
|
||||||
git = await commandManager.createCommandManager(workingDirectory, lfs)
|
const doSparseCheckout = false
|
||||||
|
git = await commandManager.createCommandManager(
|
||||||
|
workingDirectory,
|
||||||
|
lfs,
|
||||||
|
doSparseCheckout
|
||||||
|
)
|
||||||
|
|
||||||
let branches = await git.branchList(false)
|
let branches = await git.branchList(false)
|
||||||
|
|
||||||
@ -70,7 +75,12 @@ describe('git-auth-helper tests', () => {
|
|||||||
jest.spyOn(exec, 'exec').mockImplementation(mockExec)
|
jest.spyOn(exec, 'exec').mockImplementation(mockExec)
|
||||||
const workingDirectory = 'test'
|
const workingDirectory = 'test'
|
||||||
const lfs = false
|
const lfs = false
|
||||||
git = await commandManager.createCommandManager(workingDirectory, lfs)
|
const doSparseCheckout = false
|
||||||
|
git = await commandManager.createCommandManager(
|
||||||
|
workingDirectory,
|
||||||
|
lfs,
|
||||||
|
doSparseCheckout
|
||||||
|
)
|
||||||
|
|
||||||
let branches = await git.branchList(false)
|
let branches = await git.branchList(false)
|
||||||
|
|
||||||
|
@ -281,6 +281,65 @@ describe('git-directory-helper tests', () => {
|
|||||||
expect(git.branchDelete).toHaveBeenCalledWith(false, 'local-branch-2')
|
expect(git.branchDelete).toHaveBeenCalledWith(false, 'local-branch-2')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const cleanWhenSubmoduleStatusIsFalse =
|
||||||
|
'cleans when submodule status is false'
|
||||||
|
|
||||||
|
it(cleanWhenSubmoduleStatusIsFalse, async () => {
|
||||||
|
// Arrange
|
||||||
|
await setup(cleanWhenSubmoduleStatusIsFalse)
|
||||||
|
await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '')
|
||||||
|
|
||||||
|
//mock bad submodule
|
||||||
|
|
||||||
|
const submoduleStatus = git.submoduleStatus as jest.Mock<any, any>
|
||||||
|
submoduleStatus.mockImplementation(async (remote: boolean) => {
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await gitDirectoryHelper.prepareExistingDirectory(
|
||||||
|
git,
|
||||||
|
repositoryPath,
|
||||||
|
repositoryUrl,
|
||||||
|
clean,
|
||||||
|
ref
|
||||||
|
)
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const files = await fs.promises.readdir(repositoryPath)
|
||||||
|
expect(files).toHaveLength(0)
|
||||||
|
expect(git.tryClean).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
const doesNotCleanWhenSubmoduleStatusIsTrue =
|
||||||
|
'does not clean when submodule status is true'
|
||||||
|
|
||||||
|
it(doesNotCleanWhenSubmoduleStatusIsTrue, async () => {
|
||||||
|
// Arrange
|
||||||
|
await setup(doesNotCleanWhenSubmoduleStatusIsTrue)
|
||||||
|
await fs.promises.writeFile(path.join(repositoryPath, 'my-file'), '')
|
||||||
|
|
||||||
|
const submoduleStatus = git.submoduleStatus as jest.Mock<any, any>
|
||||||
|
submoduleStatus.mockImplementation(async (remote: boolean) => {
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await gitDirectoryHelper.prepareExistingDirectory(
|
||||||
|
git,
|
||||||
|
repositoryPath,
|
||||||
|
repositoryUrl,
|
||||||
|
clean,
|
||||||
|
ref
|
||||||
|
)
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
const files = await fs.promises.readdir(repositoryPath)
|
||||||
|
expect(files.sort()).toEqual(['.git', 'my-file'])
|
||||||
|
expect(git.tryClean).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
const removesLockFiles = 'removes lock files'
|
const removesLockFiles = 'removes lock files'
|
||||||
it(removesLockFiles, async () => {
|
it(removesLockFiles, async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
@ -403,6 +462,8 @@ async function setup(testName: string): Promise<void> {
|
|||||||
branchList: jest.fn(async () => {
|
branchList: jest.fn(async () => {
|
||||||
return []
|
return []
|
||||||
}),
|
}),
|
||||||
|
sparseCheckout: jest.fn(),
|
||||||
|
sparseCheckoutNonConeMode: jest.fn(),
|
||||||
checkout: jest.fn(),
|
checkout: jest.fn(),
|
||||||
checkoutDetach: jest.fn(),
|
checkoutDetach: jest.fn(),
|
||||||
config: jest.fn(),
|
config: jest.fn(),
|
||||||
@ -423,6 +484,9 @@ async function setup(testName: string): Promise<void> {
|
|||||||
submoduleForeach: jest.fn(),
|
submoduleForeach: jest.fn(),
|
||||||
submoduleSync: jest.fn(),
|
submoduleSync: jest.fn(),
|
||||||
submoduleUpdate: jest.fn(),
|
submoduleUpdate: jest.fn(),
|
||||||
|
submoduleStatus: jest.fn(async () => {
|
||||||
|
return true
|
||||||
|
}),
|
||||||
tagExists: jest.fn(),
|
tagExists: jest.fn(),
|
||||||
tryClean: jest.fn(async () => {
|
tryClean: jest.fn(async () => {
|
||||||
return true
|
return true
|
||||||
|
@ -79,6 +79,8 @@ describe('input-helper tests', () => {
|
|||||||
expect(settings.clean).toBe(true)
|
expect(settings.clean).toBe(true)
|
||||||
expect(settings.commit).toBeTruthy()
|
expect(settings.commit).toBeTruthy()
|
||||||
expect(settings.commit).toBe('1234567890123456789012345678901234567890')
|
expect(settings.commit).toBe('1234567890123456789012345678901234567890')
|
||||||
|
expect(settings.sparseCheckout).toBe(undefined)
|
||||||
|
expect(settings.sparseCheckoutConeMode).toBe(true)
|
||||||
expect(settings.fetchDepth).toBe(1)
|
expect(settings.fetchDepth).toBe(1)
|
||||||
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')
|
||||||
|
51
__test__/verify-sparse-checkout-non-cone-mode.sh
Executable file
51
__test__/verify-sparse-checkout-non-cone-mode.sh
Executable file
@ -0,0 +1,51 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Verify .git folder
|
||||||
|
if [ ! -d "./sparse-checkout-non-cone-mode/.git" ]; then
|
||||||
|
echo "Expected ./sparse-checkout-non-cone-mode/.git folder to exist"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify sparse-checkout (non-cone-mode)
|
||||||
|
cd sparse-checkout-non-cone-mode
|
||||||
|
|
||||||
|
ENABLED=$(git config --local --get-all core.sparseCheckout)
|
||||||
|
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
echo "Failed to verify that sparse-checkout is enabled"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check that sparse-checkout is enabled
|
||||||
|
if [ "$ENABLED" != "true" ]; then
|
||||||
|
echo "Expected sparse-checkout to be enabled (is: $ENABLED)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
SPARSE_CHECKOUT_FILE=$(git rev-parse --git-path info/sparse-checkout)
|
||||||
|
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
echo "Failed to validate sparse-checkout"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check that sparse-checkout list is not empty
|
||||||
|
if [ ! -f "$SPARSE_CHECKOUT_FILE" ]; then
|
||||||
|
echo "Expected sparse-checkout file to exist"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check that all folders from sparse-checkout exists
|
||||||
|
for pattern in $(cat "$SPARSE_CHECKOUT_FILE")
|
||||||
|
do
|
||||||
|
if [ ! -d "${pattern#/}" ]; then
|
||||||
|
echo "Expected directory '${pattern#/}' to exist"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Verify that the root directory is not checked out
|
||||||
|
if [ -f README.md ]; then
|
||||||
|
echo "Expected top-level files not to exist"
|
||||||
|
exit 1
|
||||||
|
fi
|
63
__test__/verify-sparse-checkout.sh
Executable file
63
__test__/verify-sparse-checkout.sh
Executable file
@ -0,0 +1,63 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Verify .git folder
|
||||||
|
if [ ! -d "./sparse-checkout/.git" ]; then
|
||||||
|
echo "Expected ./sparse-checkout/.git folder to exist"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify sparse-checkout
|
||||||
|
cd sparse-checkout
|
||||||
|
|
||||||
|
SPARSE=$(git sparse-checkout list)
|
||||||
|
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
echo "Failed to validate sparse-checkout"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check that sparse-checkout list is not empty
|
||||||
|
if [ -z "$SPARSE" ]; then
|
||||||
|
echo "Expected sparse-checkout list to not be empty"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check that all folders of the sparse checkout exist
|
||||||
|
for pattern in $SPARSE
|
||||||
|
do
|
||||||
|
if [ ! -d "$pattern" ]; then
|
||||||
|
echo "Expected directory '$pattern' to exist"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
checkSparse () {
|
||||||
|
if [ ! -d "./$1" ]; then
|
||||||
|
echo "Expected directory '$1' to exist"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
for file in $(git ls-tree -r --name-only HEAD $1)
|
||||||
|
do
|
||||||
|
if [ ! -f "$file" ]; then
|
||||||
|
echo "Expected file '$file' to exist"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check that all folders and their children have been checked out
|
||||||
|
checkSparse __test__
|
||||||
|
checkSparse .github
|
||||||
|
checkSparse dist
|
||||||
|
|
||||||
|
# Check that only sparse-checkout folders have been checked out
|
||||||
|
for pattern in $(git ls-tree --name-only HEAD)
|
||||||
|
do
|
||||||
|
if [ -d "$pattern" ]; then
|
||||||
|
if [[ "$pattern" != "__test__" && "$pattern" != ".github" && "$pattern" != "dist" ]]; then
|
||||||
|
echo "Expected directory '$pattern' to not exist"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
@ -53,6 +53,15 @@ inputs:
|
|||||||
clean:
|
clean:
|
||||||
description: 'Whether to execute `git clean -ffdx && git reset --hard HEAD` before fetching'
|
description: 'Whether to execute `git clean -ffdx && git reset --hard HEAD` before fetching'
|
||||||
default: true
|
default: true
|
||||||
|
sparse-checkout:
|
||||||
|
description: >
|
||||||
|
Do a sparse checkout on given patterns.
|
||||||
|
Each pattern should be separated with new lines
|
||||||
|
default: null
|
||||||
|
sparse-checkout-cone-mode:
|
||||||
|
description: >
|
||||||
|
Specifies whether to use cone-mode when doing a sparse checkout.
|
||||||
|
default: true
|
||||||
fetch-depth:
|
fetch-depth:
|
||||||
description: 'Number of commits to fetch. 0 indicates all history for all branches and tags.'
|
description: 'Number of commits to fetch. 0 indicates all history for all branches and tags.'
|
||||||
default: 1
|
default: 1
|
||||||
|
@ -181,7 +181,7 @@ GITHUB_WORKSPACE=/home/runner/work/foo/foo
|
|||||||
RUNNER_WORKSPACE=/home/runner/work/foo
|
RUNNER_WORKSPACE=/home/runner/work/foo
|
||||||
```
|
```
|
||||||
|
|
||||||
V2 introduces a new contraint on the checkout path. The location must now be under `github.workspace`. Whereas the checkout@v1 constraint was one level up, under `runner.workspace`.
|
V2 introduces a new constraint on the checkout path. The location must now be under `github.workspace`. Whereas the checkout@v1 constraint was one level up, under `runner.workspace`.
|
||||||
|
|
||||||
V2 no longer changes `github.workspace` to follow wherever the self repo is checked-out.
|
V2 no longer changes `github.workspace` to follow wherever the self repo is checked-out.
|
||||||
|
|
||||||
@ -287,4 +287,4 @@ Note:
|
|||||||
- Update samples to consume `actions/checkout@v2`
|
- Update samples to consume `actions/checkout@v2`
|
||||||
- Job containers now require git in the PATH for checkout, otherwise fallback to REST API
|
- Job containers now require git in the PATH for checkout, otherwise fallback to REST API
|
||||||
- Minimum git version 2.18
|
- Minimum git version 2.18
|
||||||
- Update problem matcher logic regarding source file verification (runner)
|
- Update problem matcher logic regarding source file verification (runner)
|
||||||
|
24875
dist/index.js
vendored
24875
dist/index.js
vendored
File diff suppressed because one or more lines are too long
876
package-lock.json
generated
876
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "checkout",
|
"name": "checkout",
|
||||||
"version": "3.2.0",
|
"version": "3.5.3",
|
||||||
"description": "checkout action",
|
"description": "checkout action",
|
||||||
"main": "lib/main.js",
|
"main": "lib/main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@ -30,7 +30,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.10.0",
|
"@actions/core": "^1.10.0",
|
||||||
"@actions/exec": "^1.0.1",
|
"@actions/exec": "^1.0.1",
|
||||||
"@actions/github": "^2.2.0",
|
"@actions/github": "^5.0.0",
|
||||||
"@actions/io": "^1.1.3",
|
"@actions/io": "^1.1.3",
|
||||||
"@actions/tool-cache": "^1.1.2",
|
"@actions/tool-cache": "^1.1.2",
|
||||||
"uuid": "^3.3.3"
|
"uuid": "^3.3.3"
|
||||||
|
@ -247,7 +247,7 @@ class GitAuthHelper {
|
|||||||
if (this.settings.sshKnownHosts) {
|
if (this.settings.sshKnownHosts) {
|
||||||
knownHosts += `# Begin from input known hosts\n${this.settings.sshKnownHosts}\n# end from input known hosts\n`
|
knownHosts += `# Begin from input known hosts\n${this.settings.sshKnownHosts}\n# end from input known hosts\n`
|
||||||
}
|
}
|
||||||
knownHosts += `# Begin implicitly added github.com\ngithub.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==\n# End implicitly added github.com\n`
|
knownHosts += `# Begin implicitly added github.com\ngithub.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=\n# End implicitly added github.com\n`
|
||||||
this.sshKnownHostsPath = path.join(runnerTemp, `${uniqueId}_known_hosts`)
|
this.sshKnownHostsPath = path.join(runnerTemp, `${uniqueId}_known_hosts`)
|
||||||
stateHelper.setSshKnownHostsPath(this.sshKnownHostsPath)
|
stateHelper.setSshKnownHostsPath(this.sshKnownHostsPath)
|
||||||
await fs.promises.writeFile(this.sshKnownHostsPath, knownHosts)
|
await fs.promises.writeFile(this.sshKnownHostsPath, knownHosts)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import * as exec from '@actions/exec'
|
import * as exec from '@actions/exec'
|
||||||
|
import * as fs from 'fs'
|
||||||
import * as fshelper from './fs-helper'
|
import * as fshelper from './fs-helper'
|
||||||
import * as io from '@actions/io'
|
import * as io from '@actions/io'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
@ -16,6 +17,8 @@ export interface IGitCommandManager {
|
|||||||
branchDelete(remote: boolean, branch: string): Promise<void>
|
branchDelete(remote: boolean, branch: string): Promise<void>
|
||||||
branchExists(remote: boolean, pattern: string): Promise<boolean>
|
branchExists(remote: boolean, pattern: string): Promise<boolean>
|
||||||
branchList(remote: boolean): Promise<string[]>
|
branchList(remote: boolean): Promise<string[]>
|
||||||
|
sparseCheckout(sparseCheckout: string[]): Promise<void>
|
||||||
|
sparseCheckoutNonConeMode(sparseCheckout: string[]): Promise<void>
|
||||||
checkout(ref: string, startPoint: string): Promise<void>
|
checkout(ref: string, startPoint: string): Promise<void>
|
||||||
checkoutDetach(): Promise<void>
|
checkoutDetach(): Promise<void>
|
||||||
config(
|
config(
|
||||||
@ -25,7 +28,13 @@ export interface IGitCommandManager {
|
|||||||
add?: boolean
|
add?: boolean
|
||||||
): Promise<void>
|
): Promise<void>
|
||||||
configExists(configKey: string, globalConfig?: boolean): Promise<boolean>
|
configExists(configKey: string, globalConfig?: boolean): Promise<boolean>
|
||||||
fetch(refSpec: string[], fetchDepth?: number): Promise<void>
|
fetch(
|
||||||
|
refSpec: string[],
|
||||||
|
options: {
|
||||||
|
filter?: string
|
||||||
|
fetchDepth?: number
|
||||||
|
}
|
||||||
|
): Promise<void>
|
||||||
getDefaultBranch(repositoryUrl: string): Promise<string>
|
getDefaultBranch(repositoryUrl: string): Promise<string>
|
||||||
getWorkingDirectory(): string
|
getWorkingDirectory(): string
|
||||||
init(): Promise<void>
|
init(): Promise<void>
|
||||||
@ -41,6 +50,7 @@ export interface IGitCommandManager {
|
|||||||
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): Promise<void>
|
||||||
|
submoduleStatus(): Promise<boolean>
|
||||||
tagExists(pattern: string): Promise<boolean>
|
tagExists(pattern: string): Promise<boolean>
|
||||||
tryClean(): Promise<boolean>
|
tryClean(): Promise<boolean>
|
||||||
tryConfigUnset(configKey: string, globalConfig?: boolean): Promise<boolean>
|
tryConfigUnset(configKey: string, globalConfig?: boolean): Promise<boolean>
|
||||||
@ -51,9 +61,14 @@ export interface IGitCommandManager {
|
|||||||
|
|
||||||
export async function createCommandManager(
|
export async function createCommandManager(
|
||||||
workingDirectory: string,
|
workingDirectory: string,
|
||||||
lfs: boolean
|
lfs: boolean,
|
||||||
|
doSparseCheckout: boolean
|
||||||
): Promise<IGitCommandManager> {
|
): Promise<IGitCommandManager> {
|
||||||
return await GitCommandManager.createCommandManager(workingDirectory, lfs)
|
return await GitCommandManager.createCommandManager(
|
||||||
|
workingDirectory,
|
||||||
|
lfs,
|
||||||
|
doSparseCheckout
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
class GitCommandManager {
|
class GitCommandManager {
|
||||||
@ -63,6 +78,7 @@ class GitCommandManager {
|
|||||||
}
|
}
|
||||||
private gitPath = ''
|
private gitPath = ''
|
||||||
private lfs = false
|
private lfs = false
|
||||||
|
private doSparseCheckout = false
|
||||||
private workingDirectory = ''
|
private workingDirectory = ''
|
||||||
|
|
||||||
// Private constructor; use createCommandManager()
|
// Private constructor; use createCommandManager()
|
||||||
@ -153,6 +169,27 @@ class GitCommandManager {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async sparseCheckout(sparseCheckout: string[]): Promise<void> {
|
||||||
|
await this.execGit(['sparse-checkout', 'set', ...sparseCheckout])
|
||||||
|
}
|
||||||
|
|
||||||
|
async sparseCheckoutNonConeMode(sparseCheckout: string[]): Promise<void> {
|
||||||
|
await this.execGit(['config', 'core.sparseCheckout', 'true'])
|
||||||
|
const output = await this.execGit([
|
||||||
|
'rev-parse',
|
||||||
|
'--git-path',
|
||||||
|
'info/sparse-checkout'
|
||||||
|
])
|
||||||
|
const sparseCheckoutPath = path.join(
|
||||||
|
this.workingDirectory,
|
||||||
|
output.stdout.trimRight()
|
||||||
|
)
|
||||||
|
await fs.promises.appendFile(
|
||||||
|
sparseCheckoutPath,
|
||||||
|
`\n${sparseCheckout.join('\n')}\n`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
async checkout(ref: string, startPoint: string): Promise<void> {
|
async checkout(ref: string, startPoint: string): Promise<void> {
|
||||||
const args = ['checkout', '--progress', '--force']
|
const args = ['checkout', '--progress', '--force']
|
||||||
if (startPoint) {
|
if (startPoint) {
|
||||||
@ -201,15 +238,23 @@ class GitCommandManager {
|
|||||||
return output.exitCode === 0
|
return output.exitCode === 0
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetch(refSpec: string[], fetchDepth?: number): Promise<void> {
|
async fetch(
|
||||||
|
refSpec: string[],
|
||||||
|
options: {filter?: string; fetchDepth?: number}
|
||||||
|
): Promise<void> {
|
||||||
const args = ['-c', 'protocol.version=2', 'fetch']
|
const args = ['-c', 'protocol.version=2', 'fetch']
|
||||||
if (!refSpec.some(x => x === refHelper.tagsRefSpec)) {
|
if (!refSpec.some(x => x === refHelper.tagsRefSpec)) {
|
||||||
args.push('--no-tags')
|
args.push('--no-tags')
|
||||||
}
|
}
|
||||||
|
|
||||||
args.push('--prune', '--progress', '--no-recurse-submodules')
|
args.push('--prune', '--progress', '--no-recurse-submodules')
|
||||||
if (fetchDepth && fetchDepth > 0) {
|
|
||||||
args.push(`--depth=${fetchDepth}`)
|
if (options.filter) {
|
||||||
|
args.push(`--filter=${options.filter}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.fetchDepth && options.fetchDepth > 0) {
|
||||||
|
args.push(`--depth=${options.fetchDepth}`)
|
||||||
} else if (
|
} else if (
|
||||||
fshelper.fileExistsSync(
|
fshelper.fileExistsSync(
|
||||||
path.join(this.workingDirectory, '.git', 'shallow')
|
path.join(this.workingDirectory, '.git', 'shallow')
|
||||||
@ -357,6 +402,12 @@ class GitCommandManager {
|
|||||||
await this.execGit(args)
|
await this.execGit(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async submoduleStatus(): Promise<boolean> {
|
||||||
|
const output = await this.execGit(['submodule', 'status'], true)
|
||||||
|
core.debug(output.stdout)
|
||||||
|
return output.exitCode === 0
|
||||||
|
}
|
||||||
|
|
||||||
async tagExists(pattern: string): Promise<boolean> {
|
async tagExists(pattern: string): Promise<boolean> {
|
||||||
const output = await this.execGit(['tag', '--list', pattern])
|
const output = await this.execGit(['tag', '--list', pattern])
|
||||||
return !!output.stdout.trim()
|
return !!output.stdout.trim()
|
||||||
@ -416,10 +467,15 @@ class GitCommandManager {
|
|||||||
|
|
||||||
static async createCommandManager(
|
static async createCommandManager(
|
||||||
workingDirectory: string,
|
workingDirectory: string,
|
||||||
lfs: boolean
|
lfs: boolean,
|
||||||
|
doSparseCheckout: boolean
|
||||||
): Promise<GitCommandManager> {
|
): Promise<GitCommandManager> {
|
||||||
const result = new GitCommandManager()
|
const result = new GitCommandManager()
|
||||||
await result.initializeCommandManager(workingDirectory, lfs)
|
await result.initializeCommandManager(
|
||||||
|
workingDirectory,
|
||||||
|
lfs,
|
||||||
|
doSparseCheckout
|
||||||
|
)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -469,7 +525,8 @@ class GitCommandManager {
|
|||||||
|
|
||||||
private async initializeCommandManager(
|
private async initializeCommandManager(
|
||||||
workingDirectory: string,
|
workingDirectory: string,
|
||||||
lfs: boolean
|
lfs: boolean,
|
||||||
|
doSparseCheckout: boolean
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
this.workingDirectory = workingDirectory
|
this.workingDirectory = workingDirectory
|
||||||
|
|
||||||
@ -532,6 +589,16 @@ class GitCommandManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.doSparseCheckout = doSparseCheckout
|
||||||
|
if (this.doSparseCheckout) {
|
||||||
|
// The `git sparse-checkout` command was introduced in Git v2.25.0
|
||||||
|
const minimumGitSparseCheckoutVersion = new GitVersion('2.25')
|
||||||
|
if (!gitVersion.checkMinimum(minimumGitSparseCheckoutVersion)) {
|
||||||
|
throw new Error(
|
||||||
|
`Minimum Git version required for sparse checkout is ${minimumGitSparseCheckoutVersion}. Your git ('${this.gitPath}') is ${gitVersion}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
// Set the user agent
|
// Set the user agent
|
||||||
const gitHttpUserAgent = `git/${gitVersion} (github-actions-checkout)`
|
const gitHttpUserAgent = `git/${gitVersion} (github-actions-checkout)`
|
||||||
core.debug(`Set git useragent to: ${gitHttpUserAgent}`)
|
core.debug(`Set git useragent to: ${gitHttpUserAgent}`)
|
||||||
|
@ -81,12 +81,18 @@ export async function prepareExistingDirectory(
|
|||||||
}
|
}
|
||||||
core.endGroup()
|
core.endGroup()
|
||||||
|
|
||||||
|
// Check for submodules and delete any existing files if submodules are present
|
||||||
|
if (!(await git.submoduleStatus())) {
|
||||||
|
remove = true
|
||||||
|
core.info('Bad Submodules found, removing existing files')
|
||||||
|
}
|
||||||
|
|
||||||
// Clean
|
// Clean
|
||||||
if (clean) {
|
if (clean) {
|
||||||
core.startGroup('Cleaning the repository')
|
core.startGroup('Cleaning the repository')
|
||||||
if (!(await git.tryClean())) {
|
if (!(await git.tryClean())) {
|
||||||
core.debug(
|
core.debug(
|
||||||
`The clean command failed. This might be caused by: 1) path too long, 2) permission issue, or 3) file in use. For futher investigation, manually run 'git clean -ffdx' on the directory '${repositoryPath}'.`
|
`The clean command failed. This might be caused by: 1) path too long, 2) permission issue, or 3) file in use. For further investigation, manually run 'git clean -ffdx' on the directory '${repositoryPath}'.`
|
||||||
)
|
)
|
||||||
remove = true
|
remove = true
|
||||||
} else if (!(await git.tryReset())) {
|
} else if (!(await git.tryReset())) {
|
||||||
|
@ -153,23 +153,26 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
|
|||||||
|
|
||||||
// Fetch
|
// Fetch
|
||||||
core.startGroup('Fetching the repository')
|
core.startGroup('Fetching the repository')
|
||||||
|
const fetchOptions: {filter?: string; fetchDepth?: number} = {}
|
||||||
|
if (settings.sparseCheckout) fetchOptions.filter = 'blob:none'
|
||||||
if (settings.fetchDepth <= 0) {
|
if (settings.fetchDepth <= 0) {
|
||||||
// Fetch all branches and tags
|
// Fetch all branches and tags
|
||||||
let refSpec = refHelper.getRefSpecForAllHistory(
|
let refSpec = refHelper.getRefSpecForAllHistory(
|
||||||
settings.ref,
|
settings.ref,
|
||||||
settings.commit
|
settings.commit
|
||||||
)
|
)
|
||||||
await git.fetch(refSpec)
|
await git.fetch(refSpec, fetchOptions)
|
||||||
|
|
||||||
// When all history is fetched, the ref we're interested in may have moved to a different
|
// When all history is fetched, the ref we're interested in may have moved to a different
|
||||||
// commit (push or force push). If so, fetch again with a targeted refspec.
|
// commit (push or force push). If so, fetch again with a targeted refspec.
|
||||||
if (!(await refHelper.testRef(git, settings.ref, settings.commit))) {
|
if (!(await refHelper.testRef(git, settings.ref, settings.commit))) {
|
||||||
refSpec = refHelper.getRefSpec(settings.ref, settings.commit)
|
refSpec = refHelper.getRefSpec(settings.ref, settings.commit)
|
||||||
await git.fetch(refSpec)
|
await git.fetch(refSpec, fetchOptions)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
fetchOptions.fetchDepth = settings.fetchDepth
|
||||||
const refSpec = refHelper.getRefSpec(settings.ref, settings.commit)
|
const refSpec = refHelper.getRefSpec(settings.ref, settings.commit)
|
||||||
await git.fetch(refSpec, settings.fetchDepth)
|
await git.fetch(refSpec, fetchOptions)
|
||||||
}
|
}
|
||||||
core.endGroup()
|
core.endGroup()
|
||||||
|
|
||||||
@ -185,12 +188,24 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
|
|||||||
// LFS fetch
|
// LFS fetch
|
||||||
// Explicit lfs-fetch to avoid slow checkout (fetches one lfs object at a time).
|
// Explicit lfs-fetch to avoid slow checkout (fetches one lfs object at a time).
|
||||||
// Explicit lfs fetch will fetch lfs objects in parallel.
|
// Explicit lfs fetch will fetch lfs objects in parallel.
|
||||||
if (settings.lfs) {
|
// For sparse checkouts, let `checkout` fetch the needed objects lazily.
|
||||||
|
if (settings.lfs && !settings.sparseCheckout) {
|
||||||
core.startGroup('Fetching LFS objects')
|
core.startGroup('Fetching LFS objects')
|
||||||
await git.lfsFetch(checkoutInfo.startPoint || checkoutInfo.ref)
|
await git.lfsFetch(checkoutInfo.startPoint || checkoutInfo.ref)
|
||||||
core.endGroup()
|
core.endGroup()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sparse checkout
|
||||||
|
if (settings.sparseCheckout) {
|
||||||
|
core.startGroup('Setting up sparse checkout')
|
||||||
|
if (settings.sparseCheckoutConeMode) {
|
||||||
|
await git.sparseCheckout(settings.sparseCheckout)
|
||||||
|
} else {
|
||||||
|
await git.sparseCheckoutNonConeMode(settings.sparseCheckout)
|
||||||
|
}
|
||||||
|
core.endGroup()
|
||||||
|
}
|
||||||
|
|
||||||
// Checkout
|
// Checkout
|
||||||
core.startGroup('Checking out the ref')
|
core.startGroup('Checking out the ref')
|
||||||
await git.checkout(checkoutInfo.ref, checkoutInfo.startPoint)
|
await git.checkout(checkoutInfo.ref, checkoutInfo.startPoint)
|
||||||
@ -261,7 +276,11 @@ export async function cleanup(repositoryPath: string): Promise<void> {
|
|||||||
|
|
||||||
let git: IGitCommandManager
|
let git: IGitCommandManager
|
||||||
try {
|
try {
|
||||||
git = await gitCommandManager.createCommandManager(repositoryPath, false)
|
git = await gitCommandManager.createCommandManager(
|
||||||
|
repositoryPath,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
)
|
||||||
} catch {
|
} catch {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -297,7 +316,8 @@ async function getGitCommandManager(
|
|||||||
try {
|
try {
|
||||||
return await gitCommandManager.createCommandManager(
|
return await gitCommandManager.createCommandManager(
|
||||||
settings.repositoryPath,
|
settings.repositoryPath,
|
||||||
settings.lfs
|
settings.lfs,
|
||||||
|
settings.sparseCheckout != null
|
||||||
)
|
)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Git is required for LFS
|
// Git is required for LFS
|
||||||
|
@ -29,6 +29,16 @@ export interface IGitSourceSettings {
|
|||||||
*/
|
*/
|
||||||
clean: boolean
|
clean: boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The array of folders to make the sparse checkout
|
||||||
|
*/
|
||||||
|
sparseCheckout: string[]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether to use cone mode in the sparse checkout (if any)
|
||||||
|
*/
|
||||||
|
sparseCheckoutConeMode: boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The depth when fetching
|
* The depth when fetching
|
||||||
*/
|
*/
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import * as assert from 'assert'
|
import * as assert from 'assert'
|
||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import * as fs from 'fs'
|
import * as fs from 'fs'
|
||||||
|
import * as github from '@actions/github'
|
||||||
import * as io from '@actions/io'
|
import * as io from '@actions/io'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import * as retryHelper from './retry-helper'
|
import * as retryHelper from './retry-helper'
|
||||||
import * as toolCache from '@actions/tool-cache'
|
import * as toolCache from '@actions/tool-cache'
|
||||||
import {default as uuid} from 'uuid/v4'
|
import {default as uuid} from 'uuid/v4'
|
||||||
import {getOctokit, Octokit} from './octokit-provider'
|
import {getServerApiUrl} from './url-helper'
|
||||||
|
|
||||||
const IS_WINDOWS = process.platform === 'win32'
|
const IS_WINDOWS = process.platform === 'win32'
|
||||||
|
|
||||||
@ -84,11 +85,13 @@ export async function getDefaultBranch(
|
|||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
return await retryHelper.execute(async () => {
|
return await retryHelper.execute(async () => {
|
||||||
core.info('Retrieving the default branch name')
|
core.info('Retrieving the default branch name')
|
||||||
const octokit = getOctokit(authToken, {baseUrl: baseUrl})
|
const octokit = github.getOctokit(authToken, {
|
||||||
|
baseUrl: getServerApiUrl(baseUrl)
|
||||||
|
})
|
||||||
let result: string
|
let result: string
|
||||||
try {
|
try {
|
||||||
// Get the default branch from the repo info
|
// Get the default branch from the repo info
|
||||||
const response = await octokit.repos.get({owner, repo})
|
const response = await octokit.rest.repos.get({owner, repo})
|
||||||
result = response.data.default_branch
|
result = response.data.default_branch
|
||||||
assert.ok(result, 'default_branch cannot be empty')
|
assert.ok(result, 'default_branch cannot be empty')
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -125,19 +128,16 @@ async function downloadArchive(
|
|||||||
commit: string,
|
commit: string,
|
||||||
baseUrl?: string
|
baseUrl?: string
|
||||||
): Promise<Buffer> {
|
): Promise<Buffer> {
|
||||||
const octokit = getOctokit(authToken, {baseUrl: baseUrl})
|
const octokit = github.getOctokit(authToken, {
|
||||||
const params: Octokit.ReposGetArchiveLinkParams = {
|
baseUrl: getServerApiUrl(baseUrl)
|
||||||
|
})
|
||||||
|
const download = IS_WINDOWS
|
||||||
|
? octokit.rest.repos.downloadZipballArchive
|
||||||
|
: octokit.rest.repos.downloadTarballArchive
|
||||||
|
const response = await download({
|
||||||
owner: owner,
|
owner: owner,
|
||||||
repo: repo,
|
repo: repo,
|
||||||
archive_format: IS_WINDOWS ? 'zipball' : 'tarball',
|
|
||||||
ref: commit || ref
|
ref: commit || ref
|
||||||
}
|
})
|
||||||
const response = await octokit.repos.getArchiveLink(params)
|
return Buffer.from(response.data as ArrayBuffer) // response.data is ArrayBuffer
|
||||||
if (response.status != 200) {
|
|
||||||
throw new Error(
|
|
||||||
`Unexpected response from GitHub API. Status: ${response.status}, Data: ${response.data}`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return Buffer.from(response.data) // response.data is ArrayBuffer
|
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,17 @@ export async function getInputs(): Promise<IGitSourceSettings> {
|
|||||||
result.clean = (core.getInput('clean') || 'true').toUpperCase() === 'TRUE'
|
result.clean = (core.getInput('clean') || 'true').toUpperCase() === 'TRUE'
|
||||||
core.debug(`clean = ${result.clean}`)
|
core.debug(`clean = ${result.clean}`)
|
||||||
|
|
||||||
|
// Sparse checkout
|
||||||
|
const sparseCheckout = core.getMultilineInput('sparse-checkout')
|
||||||
|
if (sparseCheckout.length) {
|
||||||
|
result.sparseCheckout = sparseCheckout
|
||||||
|
core.debug(`sparse checkout = ${result.sparseCheckout}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
result.sparseCheckoutConeMode =
|
||||||
|
(core.getInput('sparse-checkout-cone-mode') || 'true').toUpperCase() ===
|
||||||
|
'TRUE'
|
||||||
|
|
||||||
// Fetch depth
|
// Fetch depth
|
||||||
result.fetchDepth = Math.floor(Number(core.getInput('fetch-depth') || '1'))
|
result.fetchDepth = Math.floor(Number(core.getInput('fetch-depth') || '1'))
|
||||||
if (isNaN(result.fetchDepth) || result.fetchDepth < 0) {
|
if (isNaN(result.fetchDepth) || result.fetchDepth < 0) {
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
import * as github from '@actions/github'
|
|
||||||
import {Octokit} from '@octokit/rest'
|
|
||||||
import {getServerApiUrl} from './url-helper'
|
|
||||||
|
|
||||||
// Centralize all Octokit references by re-exporting
|
|
||||||
export {Octokit} from '@octokit/rest'
|
|
||||||
|
|
||||||
export type OctokitOptions = {
|
|
||||||
baseUrl?: string
|
|
||||||
userAgent?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getOctokit(authToken: string, opts: OctokitOptions) {
|
|
||||||
const options: Octokit.Options = {
|
|
||||||
baseUrl: getServerApiUrl(opts.baseUrl)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.userAgent) {
|
|
||||||
options.userAgent = opts.userAgent
|
|
||||||
}
|
|
||||||
|
|
||||||
return new github.GitHub(authToken, options)
|
|
||||||
}
|
|
@ -1,8 +1,7 @@
|
|||||||
import {IGitCommandManager} from './git-command-manager'
|
import {IGitCommandManager} from './git-command-manager'
|
||||||
import * as core from '@actions/core'
|
import * as core from '@actions/core'
|
||||||
import * as github from '@actions/github'
|
import * as github from '@actions/github'
|
||||||
import {getOctokit} from './octokit-provider'
|
import {getServerApiUrl, isGhes} from './url-helper'
|
||||||
import {isGhes} from './url-helper'
|
|
||||||
|
|
||||||
export const tagsRefSpec = '+refs/tags/*:refs/tags/*'
|
export const tagsRefSpec = '+refs/tags/*:refs/tags/*'
|
||||||
|
|
||||||
@ -245,15 +244,18 @@ export async function checkCommitInfo(
|
|||||||
core.debug(
|
core.debug(
|
||||||
`Expected head sha ${expectedHeadSha}; actual head sha ${actualHeadSha}`
|
`Expected head sha ${expectedHeadSha}; actual head sha ${actualHeadSha}`
|
||||||
)
|
)
|
||||||
const octokit = getOctokit(token, {
|
const octokit = github.getOctokit(token, {
|
||||||
baseUrl: baseUrl,
|
baseUrl: getServerApiUrl(baseUrl),
|
||||||
userAgent: `actions-checkout-tracepoint/1.0 (code=STALE_MERGE;owner=${repositoryOwner};repo=${repositoryName};pr=${fromPayload(
|
userAgent: `actions-checkout-tracepoint/1.0 (code=STALE_MERGE;owner=${repositoryOwner};repo=${repositoryName};pr=${fromPayload(
|
||||||
'number'
|
'number'
|
||||||
)};run_id=${
|
)};run_id=${
|
||||||
process.env['GITHUB_RUN_ID']
|
process.env['GITHUB_RUN_ID']
|
||||||
};expected_head_sha=${expectedHeadSha};actual_head_sha=${actualHeadSha})`
|
};expected_head_sha=${expectedHeadSha};actual_head_sha=${actualHeadSha})`
|
||||||
})
|
})
|
||||||
await octokit.repos.get({owner: repositoryOwner, repo: repositoryName})
|
await octokit.rest.repos.get({
|
||||||
|
owner: repositoryOwner,
|
||||||
|
repo: repositoryName
|
||||||
|
})
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
core.debug(
|
core.debug(
|
||||||
|
Reference in New Issue
Block a user