Compare commits

...

6 Commits

Author SHA1 Message Date
1e31de5234 Update docs 2023-10-17 15:38:19 +00:00
3df4ab11eb Release 4.0.0 (#1447)
* Release 4.0.0

* Add new major version to workflow
2023-09-04 14:19:40 +02:00
8b5e8b7687 Support fetching without the --progress option (#1067)
Setting the `show-progress` option to false in the `with` section of the
workflow step will cause git fetch to run without `--progress`.

The motivation is to be able to suppress the noisy progress status
output which adds many hundreds of "remote: Counting objects: 85%
(386/453)" and similar lines in the workflow log.

This should be sufficient to resolve #894 and its older friends,
though the solution is different to the one proposed there because
it doesn't use the --quiet flag. IIUC git doesn't show the progress
status by default since the output is not a terminal, so that's why
removing the --progress option is all that's needed.

Adding the --quiet flag doesn't make a lot of difference once the
--progress flag is removed, and actually I think using --quiet would
suppress some other more useful output that would be better left
visible.

Signed-off-by: Simon Baird <sbaird@redhat.com>
2023-09-01 14:19:18 -04:00
97a652b800 Update default runtime to node20 (#1436)
* .

* update workflows
2023-08-29 17:01:52 +02:00
f43a0e5ff2 Release 3.6.0 (#1437) 2023-08-24 09:54:47 -04:00
7739b9ba2e Add option to fetch tags even if fetch-depth > 0 (#579)
* Add option to fetch tags even if fetch-depth > 0

* Add jest tests for fetchDepth and fetchTags options
2023-08-16 16:34:54 -04:00
17 changed files with 409 additions and 15947 deletions

View File

@ -24,10 +24,10 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Set Node.js 16.x
- name: Set Node.js 20.x
uses: actions/setup-node@v1
with:
node-version: 16.x
node-version: 20.x
- name: Install dependencies
run: npm ci

View File

@ -13,7 +13,7 @@ jobs:
steps:
- uses: actions/setup-node@v1
with:
node-version: 16.x
node-version: 20.x
- uses: actions/checkout@v3
- run: npm ci
- run: npm run build

View File

@ -11,6 +11,7 @@ on:
type: choice
description: The major version to update
options:
- v4
- v3
- v2

View File

@ -1,5 +1,13 @@
# Changelog
## v4.0.0
- [Support fetching without the --progress option](https://github.com/actions/checkout/pull/1067)
- [Update to node20](https://github.com/actions/checkout/pull/1436)
## v3.6.0
- [Fix: Mark test scripts with Bash'isms to be run via Bash](https://github.com/actions/checkout/pull/1377)
- [Add option to fetch tags even if fetch-depth > 0](https://github.com/actions/checkout/pull/579)
## 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)

View File

@ -1,6 +1,6 @@
[![Build and Test](https://github.com/actions/checkout/actions/workflows/test.yml/badge.svg)](https://github.com/actions/checkout/actions/workflows/test.yml)
# Checkout V3
# Checkout V4
This action checks-out your repository under `$GITHUB_WORKSPACE`, so your workflow can access it.
@ -12,14 +12,14 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
# What's new
- Updated to the node16 runtime by default
- This requires a minimum [Actions Runner](https://github.com/actions/runner/releases/tag/v2.285.0) version of v2.285.0 to run, which is by default available in GHES 3.4 or later.
- Updated to the node20 runtime by default
- This requires a minimum [Actions Runner](https://github.com/actions/runner/releases/tag/v2.285.0) version of v2.308.0 to run, which is by default available in GHES 3.11 or later.
# Usage
<!-- start usage -->
```yaml
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
# Repository name with owner. For example, actions/checkout
# Default: ${{ github.repository }}
@ -87,6 +87,14 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
# Default: 1
fetch-depth: ''
# Whether to fetch tags, even if fetch-depth > 0.
# Default: false
fetch-tags: ''
# Whether to show progress status output when fetching.
# Default: true
show-progress: ''
# Whether to download Git-LFS files
# Default: false
lfs: ''
@ -131,7 +139,7 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
## Fetch only the root files
```yaml
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
sparse-checkout: .
```
@ -139,7 +147,7 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
## Fetch only the root files and `.github` and `src` folder
```yaml
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
sparse-checkout: |
.github
@ -149,7 +157,7 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
## Fetch only a single file
```yaml
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
sparse-checkout: |
README.md
@ -159,7 +167,7 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
## Fetch all history for all tags and branches
```yaml
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
```
@ -167,7 +175,7 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
## Checkout a different branch
```yaml
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
ref: my-branch
```
@ -175,7 +183,7 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
## Checkout HEAD^
```yaml
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 2
- run: git checkout HEAD^
@ -185,12 +193,12 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
```yaml
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
path: main
- name: Checkout tools repo
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
repository: my-org/my-tools
path: my-tools
@ -201,10 +209,10 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
```yaml
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Checkout tools repo
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
repository: my-org/my-tools
path: my-tools
@ -215,12 +223,12 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
```yaml
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
path: main
- name: Checkout private tools
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
repository: my-org/my-private-tools
token: ${{ secrets.GH_PAT }} # `GH_PAT` is a secret that contains your PAT
@ -233,7 +241,7 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
## Checkout pull request HEAD commit instead of merge commit
```yaml
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
```
@ -249,7 +257,7 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
```
## Push a commit using the built-in token
@ -260,7 +268,7 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- run: |
date > generated.txt
git config user.name github-actions

View File

@ -805,6 +805,8 @@ async function setup(testName: string): Promise<void> {
sparseCheckout: [],
sparseCheckoutConeMode: true,
fetchDepth: 1,
fetchTags: false,
showProgress: true,
lfs: false,
submodules: false,
nestedSubmodules: false,

View File

@ -88,3 +88,291 @@ describe('git-auth-helper tests', () => {
expect(branches.sort()).toEqual(['foo'].sort())
})
})
describe('Test fetchDepth and fetchTags options', () => {
beforeEach(async () => {
jest.spyOn(fshelper, 'fileExistsSync').mockImplementation(jest.fn())
jest.spyOn(fshelper, 'directoryExistsSync').mockImplementation(jest.fn())
mockExec.mockImplementation((path, args, options) => {
console.log(args, options.listeners.stdout)
if (args.includes('version')) {
options.listeners.stdout(Buffer.from('2.18'))
}
return 0
})
})
afterEach(() => {
jest.restoreAllMocks()
})
it('should call execGit with the correct arguments when fetchDepth is 0 and fetchTags is true', async () => {
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', 'refspec2']
const options = {
filter: 'filterValue',
fetchDepth: 0,
fetchTags: true
}
await git.fetch(refSpec, options)
expect(mockExec).toHaveBeenCalledWith(
expect.any(String),
[
'-c',
'protocol.version=2',
'fetch',
'--prune',
'--no-recurse-submodules',
'--filter=filterValue',
'origin',
'refspec1',
'refspec2'
],
expect.any(Object)
)
})
it('should call execGit with the correct arguments when fetchDepth is 0 and fetchTags is false', async () => {
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', 'refspec2']
const options = {
filter: 'filterValue',
fetchDepth: 0,
fetchTags: false
}
await git.fetch(refSpec, options)
expect(mockExec).toHaveBeenCalledWith(
expect.any(String),
[
'-c',
'protocol.version=2',
'fetch',
'--no-tags',
'--prune',
'--no-recurse-submodules',
'--filter=filterValue',
'origin',
'refspec1',
'refspec2'
],
expect.any(Object)
)
})
it('should call execGit with the correct arguments when fetchDepth is 1 and fetchTags is false', async () => {
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', 'refspec2']
const options = {
filter: 'filterValue',
fetchDepth: 1,
fetchTags: false
}
await git.fetch(refSpec, options)
expect(mockExec).toHaveBeenCalledWith(
expect.any(String),
[
'-c',
'protocol.version=2',
'fetch',
'--no-tags',
'--prune',
'--no-recurse-submodules',
'--filter=filterValue',
'--depth=1',
'origin',
'refspec1',
'refspec2'
],
expect.any(Object)
)
})
it('should call execGit with the correct arguments when fetchDepth is 1 and fetchTags is true', async () => {
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', 'refspec2']
const options = {
filter: 'filterValue',
fetchDepth: 1,
fetchTags: true
}
await git.fetch(refSpec, options)
expect(mockExec).toHaveBeenCalledWith(
expect.any(String),
[
'-c',
'protocol.version=2',
'fetch',
'--prune',
'--no-recurse-submodules',
'--filter=filterValue',
'--depth=1',
'origin',
'refspec1',
'refspec2'
],
expect.any(Object)
)
})
it('should call execGit with the correct arguments when showProgress is true', async () => {
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', 'refspec2']
const options = {
filter: 'filterValue',
showProgress: true
}
await git.fetch(refSpec, options)
expect(mockExec).toHaveBeenCalledWith(
expect.any(String),
[
'-c',
'protocol.version=2',
'fetch',
'--no-tags',
'--prune',
'--no-recurse-submodules',
'--progress',
'--filter=filterValue',
'origin',
'refspec1',
'refspec2'
],
expect.any(Object)
)
})
it('should call execGit with the correct arguments when fetchDepth is 42 and showProgress is true', async () => {
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', 'refspec2']
const options = {
filter: 'filterValue',
fetchDepth: 42,
showProgress: true
}
await git.fetch(refSpec, options)
expect(mockExec).toHaveBeenCalledWith(
expect.any(String),
[
'-c',
'protocol.version=2',
'fetch',
'--no-tags',
'--prune',
'--no-recurse-submodules',
'--progress',
'--filter=filterValue',
'--depth=42',
'origin',
'refspec1',
'refspec2'
],
expect.any(Object)
)
})
it('should call execGit with the correct arguments when fetchTags is true and showProgress is true', async () => {
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', 'refspec2']
const options = {
filter: 'filterValue',
fetchTags: true,
showProgress: true
}
await git.fetch(refSpec, options)
expect(mockExec).toHaveBeenCalledWith(
expect.any(String),
[
'-c',
'protocol.version=2',
'fetch',
'--prune',
'--no-recurse-submodules',
'--progress',
'--filter=filterValue',
'origin',
'refspec1',
'refspec2'
],
expect.any(Object)
)
})
})

View File

@ -82,6 +82,8 @@ describe('input-helper tests', () => {
expect(settings.sparseCheckout).toBe(undefined)
expect(settings.sparseCheckoutConeMode).toBe(true)
expect(settings.fetchDepth).toBe(1)
expect(settings.fetchTags).toBe(false)
expect(settings.showProgress).toBe(true)
expect(settings.lfs).toBe(false)
expect(settings.ref).toBe('refs/heads/some-ref')
expect(settings.repositoryName).toBe('some-repo')

View File

@ -65,6 +65,12 @@ inputs:
fetch-depth:
description: 'Number of commits to fetch. 0 indicates all history for all branches and tags.'
default: 1
fetch-tags:
description: 'Whether to fetch tags, even if fetch-depth > 0.'
default: false
show-progress:
description: 'Whether to show progress status output when fetching.'
default: true
lfs:
description: 'Whether to download Git-LFS files'
default: false
@ -84,6 +90,6 @@ inputs:
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
runs:
using: node16
using: node20
main: dist/index.js
post: dist/index.js

20
dist/index.js vendored
View File

@ -637,10 +637,13 @@ 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)) {
if (!refSpec.some(x => x === refHelper.tagsRefSpec) && !options.fetchTags) {
args.push('--no-tags');
}
args.push('--prune', '--progress', '--no-recurse-submodules');
args.push('--prune', '--no-recurse-submodules');
if (options.showProgress) {
args.push('--progress');
}
if (options.filter) {
args.push(`--filter=${options.filter}`);
}
@ -718,8 +721,8 @@ class GitCommandManager {
}
log1(format) {
return __awaiter(this, void 0, void 0, function* () {
var args = format ? ['log', '-1', format] : ['log', '-1'];
var silent = format ? false : true;
const args = format ? ['log', '-1', format] : ['log', '-1'];
const silent = format ? false : true;
const output = yield this.execGit(args, false, silent);
return output.stdout;
});
@ -1256,6 +1259,7 @@ function getSource(settings) {
}
else {
fetchOptions.fetchDepth = settings.fetchDepth;
fetchOptions.fetchTags = settings.fetchTags;
const refSpec = refHelper.getRefSpec(settings.ref, settings.commit);
yield git.fetch(refSpec, fetchOptions);
}
@ -1734,6 +1738,14 @@ function getInputs() {
result.fetchDepth = 0;
}
core.debug(`fetch depth = ${result.fetchDepth}`);
// Fetch tags
result.fetchTags =
(core.getInput('fetch-tags') || 'false').toUpperCase() === 'TRUE';
core.debug(`fetch tags = ${result.fetchTags}`);
// Show fetch progress
result.showProgress =
(core.getInput('show-progress') || 'true').toUpperCase() === 'TRUE';
core.debug(`show progress = ${result.showProgress}`);
// LFS
result.lfs = (core.getInput('lfs') || 'false').toUpperCase() === 'TRUE';
core.debug(`lfs = ${result.lfs}`);

15919
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "checkout",
"version": "3.5.3",
"version": "4.0.0",
"description": "checkout action",
"main": "lib/main.js",
"scripts": {
@ -37,7 +37,7 @@
},
"devDependencies": {
"@types/jest": "^27.0.2",
"@types/node": "^12.7.12",
"@types/node": "^20.5.3",
"@types/uuid": "^3.4.6",
"@typescript-eslint/eslint-plugin": "^5.45.0",
"@typescript-eslint/parser": "^5.45.0",
@ -52,4 +52,4 @@
"ts-jest": "^27.0.7",
"typescript": "^4.4.4"
}
}
}

View File

@ -33,6 +33,8 @@ export interface IGitCommandManager {
options: {
filter?: string
fetchDepth?: number
fetchTags?: boolean
showProgress?: boolean
}
): Promise<void>
getDefaultBranch(repositoryUrl: string): Promise<string>
@ -240,14 +242,22 @@ class GitCommandManager {
async fetch(
refSpec: string[],
options: {filter?: string; fetchDepth?: number}
options: {
filter?: string
fetchDepth?: number
fetchTags?: boolean
showProgress?: boolean
}
): Promise<void> {
const args = ['-c', 'protocol.version=2', 'fetch']
if (!refSpec.some(x => x === refHelper.tagsRefSpec)) {
if (!refSpec.some(x => x === refHelper.tagsRefSpec) && !options.fetchTags) {
args.push('--no-tags')
}
args.push('--prune', '--progress', '--no-recurse-submodules')
args.push('--prune', '--no-recurse-submodules')
if (options.showProgress) {
args.push('--progress')
}
if (options.filter) {
args.push(`--filter=${options.filter}`)
@ -333,8 +343,8 @@ class GitCommandManager {
}
async log1(format?: string): Promise<string> {
var args = format ? ['log', '-1', format] : ['log', '-1']
var silent = format ? false : true
const args = format ? ['log', '-1', format] : ['log', '-1']
const silent = format ? false : true
const output = await this.execGit(args, false, silent)
return output.stdout
}

View File

@ -153,7 +153,12 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
// Fetch
core.startGroup('Fetching the repository')
const fetchOptions: {filter?: string; fetchDepth?: number} = {}
const fetchOptions: {
filter?: string
fetchDepth?: number
fetchTags?: boolean
showProgress?: boolean
} = {}
if (settings.sparseCheckout) fetchOptions.filter = 'blob:none'
if (settings.fetchDepth <= 0) {
// Fetch all branches and tags
@ -171,6 +176,7 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
}
} else {
fetchOptions.fetchDepth = settings.fetchDepth
fetchOptions.fetchTags = settings.fetchTags
const refSpec = refHelper.getRefSpec(settings.ref, settings.commit)
await git.fetch(refSpec, fetchOptions)
}

View File

@ -44,6 +44,16 @@ export interface IGitSourceSettings {
*/
fetchDepth: number
/**
* Fetch tags, even if fetchDepth > 0 (default: false)
*/
fetchTags: boolean
/**
* Indicates whether to use the --progress option when fetching
*/
showProgress: boolean
/**
* Indicates whether to fetch LFS objects
*/

View File

@ -100,6 +100,16 @@ export async function getInputs(): Promise<IGitSourceSettings> {
}
core.debug(`fetch depth = ${result.fetchDepth}`)
// Fetch tags
result.fetchTags =
(core.getInput('fetch-tags') || 'false').toUpperCase() === 'TRUE'
core.debug(`fetch tags = ${result.fetchTags}`)
// Show fetch progress
result.showProgress =
(core.getInput('show-progress') || 'true').toUpperCase() === 'TRUE'
core.debug(`show progress = ${result.showProgress}`)
// LFS
result.lfs = (core.getInput('lfs') || 'false').toUpperCase() === 'TRUE'
core.debug(`lfs = ${result.lfs}`)

View File

@ -120,7 +120,7 @@ function updateUsage(
}
updateUsage(
'actions/checkout@v3',
'actions/checkout@v4',
path.join(__dirname, '..', '..', 'action.yml'),
path.join(__dirname, '..', '..', 'README.md')
)