mirror of
https://github.com/actions/checkout.git
synced 2024-12-22 16:47:43 +01:00
Merge branch 'main' into patch-1
This commit is contained in:
commit
d86d1a437e
4
.github/workflows/check-dist.yml
vendored
4
.github/workflows/check-dist.yml
vendored
@ -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
|
||||
|
4
.github/workflows/codeql-analysis.yml
vendored
4
.github/workflows/codeql-analysis.yml
vendored
@ -42,7 +42,7 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@ -55,4 +55,4 @@ jobs:
|
||||
- run: rm -rf dist # We want code scanning to analyze lib instead (individual .js files)
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
39
.github/workflows/test.yml
vendored
39
.github/workflows/test.yml
vendored
@ -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
|
||||
@ -72,6 +72,43 @@ jobs:
|
||||
shell: bash
|
||||
run: __test__/verify-side-by-side.sh
|
||||
|
||||
# Filter
|
||||
- name: Fetch filter
|
||||
uses: ./
|
||||
with:
|
||||
filter: 'blob:none'
|
||||
path: fetch-filter
|
||||
|
||||
- name: Verify fetch filter
|
||||
run: __test__/verify-fetch-filter.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
|
||||
- name: Checkout LFS
|
||||
uses: ./
|
||||
|
10
.github/workflows/update-main-version.yml
vendored
10
.github/workflows/update-main-version.yml
vendored
@ -1,5 +1,5 @@
|
||||
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:
|
||||
workflow_dispatch:
|
||||
@ -7,18 +7,20 @@ on:
|
||||
target:
|
||||
description: The tag or reference to use
|
||||
required: true
|
||||
main_version:
|
||||
major_version:
|
||||
type: choice
|
||||
description: The main version to update
|
||||
description: The major version to update
|
||||
options:
|
||||
- v4
|
||||
- v3
|
||||
- v2
|
||||
|
||||
jobs:
|
||||
tag:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
TARGET: ${{ github.event.inputs.target }}
|
||||
MAIN_VERSION: ${{ github.event.inputs.main_version }}
|
||||
MAIN_VERSION: ${{ github.event.inputs.major_version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
|
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/@actions/io.dep.yml
generated
BIN
.licenses/npm/@actions/io.dep.yml
generated
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/qs.dep.yml
generated
BIN
.licenses/npm/qs.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.
43
CHANGELOG.md
43
CHANGELOG.md
@ -1,5 +1,48 @@
|
||||
# Changelog
|
||||
|
||||
## v4.1.0
|
||||
- [Add support for partial checkout filters](https://github.com/actions/checkout/pull/1396)
|
||||
|
||||
## 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)
|
||||
- [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
|
||||
- [Upgrade codeql actions to v2](https://github.com/actions/checkout/pull/1209)
|
||||
- [Upgrade dependencies](https://github.com/actions/checkout/pull/1210)
|
||||
- [Upgrade @actions/io](https://github.com/actions/checkout/pull/1225)
|
||||
|
||||
## v3.3.0
|
||||
- [Implement branch list using callbacks from exec function](https://github.com/actions/checkout/pull/1045)
|
||||
- [Add in explicit reference to private checkout options](https://github.com/actions/checkout/pull/1050)
|
||||
- [Fix comment typos (that got added in #770)](https://github.com/actions/checkout/pull/1057)
|
||||
|
||||
## v3.2.0
|
||||
- [Add GitHub Action to perform release](https://github.com/actions/checkout/pull/942)
|
||||
- [Fix status badge](https://github.com/actions/checkout/pull/967)
|
||||
- [Replace datadog/squid with ubuntu/squid Docker image](https://github.com/actions/checkout/pull/1002)
|
||||
- [Wrap pipeline commands for submoduleForeach in quotes](https://github.com/actions/checkout/pull/964)
|
||||
- [Update @actions/io to 1.1.2](https://github.com/actions/checkout/pull/1029)
|
||||
- [Upgrading version to 3.2.0](https://github.com/actions/checkout/pull/1039)
|
||||
|
||||
## v3.1.0
|
||||
- [Use @actions/core `saveState` and `getState`](https://github.com/actions/checkout/pull/939)
|
||||
- [Add `github-server-url` input](https://github.com/actions/checkout/pull/922)
|
||||
|
@ -1 +1 @@
|
||||
* @actions/actions-runtime
|
||||
* @actions/actions-launch
|
||||
|
87
README.md
87
README.md
@ -1,10 +1,10 @@
|
||||
[![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.
|
||||
|
||||
Only a single commit is fetched by default, for the ref/SHA that triggered the workflow. Set `fetch-depth: 0` to fetch all history for all branches and tags. Refer [here](https://help.github.com/en/articles/events-that-trigger-workflows) to learn which commit `$GITHUB_SHA` points to for different events.
|
||||
Only a single commit is fetched by default, for the ref/SHA that triggered the workflow. Set `fetch-depth: 0` to fetch all history for all branches and tags. Refer [here](https://docs.github.com/actions/using-workflows/events-that-trigger-workflows) to learn which commit `$GITHUB_SHA` points to for different events.
|
||||
|
||||
The auth token is persisted in the local git config. This enables your scripts to run authenticated git commands. The token is removed during post-job cleanup. Set `persist-credentials: false` to opt-out.
|
||||
|
||||
@ -12,14 +12,13 @@ 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.
|
||||
Please refer to the [release page](https://github.com/actions/checkout/releases/latest) for the latest release notes.
|
||||
|
||||
# Usage
|
||||
|
||||
<!-- start usage -->
|
||||
```yaml
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
# Repository name with owner. For example, actions/checkout
|
||||
# Default: ${{ github.repository }}
|
||||
@ -74,10 +73,31 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
|
||||
# Default: true
|
||||
clean: ''
|
||||
|
||||
# Partially clone against a given filter. Overrides sparse-checkout if set.
|
||||
# Default: null
|
||||
filter: ''
|
||||
|
||||
# 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.
|
||||
# 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: ''
|
||||
@ -106,6 +126,9 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
|
||||
|
||||
# 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)
|
||||
- [Checkout a different branch](#Checkout-a-different-branch)
|
||||
- [Checkout HEAD^](#Checkout-HEAD)
|
||||
@ -116,10 +139,38 @@ 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)
|
||||
- [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@v4
|
||||
with:
|
||||
sparse-checkout: .
|
||||
```
|
||||
|
||||
## Fetch only the root files and `.github` and `src` folder
|
||||
|
||||
```yaml
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: |
|
||||
.github
|
||||
src
|
||||
```
|
||||
|
||||
## Fetch only a single file
|
||||
|
||||
```yaml
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: |
|
||||
README.md
|
||||
sparse-checkout-cone-mode: false
|
||||
```
|
||||
|
||||
## Fetch all history for all tags and branches
|
||||
|
||||
```yaml
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
```
|
||||
@ -127,7 +178,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
|
||||
```
|
||||
@ -135,7 +186,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^
|
||||
@ -145,40 +196,42 @@ 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
|
||||
```
|
||||
> - If your secondary repository is private you will need to add the option noted in [Checkout multiple repos (private)](#Checkout-multiple-repos-private)
|
||||
|
||||
## Checkout multiple repos (nested)
|
||||
|
||||
```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
|
||||
```
|
||||
> - If your secondary repository is private you will need to add the option noted in [Checkout multiple repos (private)](#Checkout-multiple-repos-private)
|
||||
|
||||
## Checkout multiple repos (private)
|
||||
|
||||
```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
|
||||
@ -191,7 +244,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 }}
|
||||
```
|
||||
@ -207,7 +260,7 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
```
|
||||
|
||||
## Push a commit using the built-in token
|
||||
@ -218,7 +271,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
|
||||
|
@ -727,6 +727,8 @@ async function setup(testName: string): Promise<void> {
|
||||
branchDelete: jest.fn(),
|
||||
branchExists: jest.fn(),
|
||||
branchList: jest.fn(),
|
||||
sparseCheckout: jest.fn(),
|
||||
sparseCheckoutNonConeMode: jest.fn(),
|
||||
checkout: jest.fn(),
|
||||
checkoutDetach: jest.fn(),
|
||||
config: jest.fn(
|
||||
@ -770,6 +772,9 @@ async function setup(testName: string): Promise<void> {
|
||||
return ''
|
||||
}),
|
||||
submoduleSync: jest.fn(),
|
||||
submoduleStatus: jest.fn(async () => {
|
||||
return true
|
||||
}),
|
||||
submoduleUpdate: jest.fn(),
|
||||
tagExists: jest.fn(),
|
||||
tryClean: jest.fn(),
|
||||
@ -797,7 +802,12 @@ async function setup(testName: string): Promise<void> {
|
||||
authToken: 'some auth token',
|
||||
clean: true,
|
||||
commit: '',
|
||||
filter: undefined,
|
||||
sparseCheckout: [],
|
||||
sparseCheckoutConeMode: true,
|
||||
fetchDepth: 1,
|
||||
fetchTags: false,
|
||||
showProgress: true,
|
||||
lfs: false,
|
||||
submodules: false,
|
||||
nestedSubmodules: false,
|
||||
|
378
__test__/git-command-manager.test.ts
Normal file
378
__test__/git-command-manager.test.ts
Normal file
@ -0,0 +1,378 @@
|
||||
import * as exec from '@actions/exec'
|
||||
import * as fshelper from '../lib/fs-helper'
|
||||
import * as commandManager from '../lib/git-command-manager'
|
||||
|
||||
let git: commandManager.IGitCommandManager
|
||||
let mockExec = jest.fn()
|
||||
|
||||
describe('git-auth-helper tests', () => {
|
||||
beforeAll(async () => {})
|
||||
|
||||
beforeEach(async () => {
|
||||
jest.spyOn(fshelper, 'fileExistsSync').mockImplementation(jest.fn())
|
||||
jest.spyOn(fshelper, 'directoryExistsSync').mockImplementation(jest.fn())
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks()
|
||||
})
|
||||
|
||||
afterAll(() => {})
|
||||
|
||||
it('branch list matches', async () => {
|
||||
mockExec.mockImplementation((path, args, options) => {
|
||||
console.log(args, options.listeners.stdout)
|
||||
|
||||
if (args.includes('version')) {
|
||||
options.listeners.stdout(Buffer.from('2.18'))
|
||||
return 0
|
||||
}
|
||||
|
||||
if (args.includes('rev-parse')) {
|
||||
options.listeners.stdline(Buffer.from('refs/heads/foo'))
|
||||
options.listeners.stdline(Buffer.from('refs/heads/bar'))
|
||||
return 0
|
||||
}
|
||||
|
||||
return 1
|
||||
})
|
||||
jest.spyOn(exec, 'exec').mockImplementation(mockExec)
|
||||
const workingDirectory = 'test'
|
||||
const lfs = false
|
||||
const doSparseCheckout = false
|
||||
git = await commandManager.createCommandManager(
|
||||
workingDirectory,
|
||||
lfs,
|
||||
doSparseCheckout
|
||||
)
|
||||
|
||||
let branches = await git.branchList(false)
|
||||
|
||||
expect(branches).toHaveLength(2)
|
||||
expect(branches.sort()).toEqual(['foo', 'bar'].sort())
|
||||
})
|
||||
|
||||
it('ambiguous ref name output is captured', async () => {
|
||||
mockExec.mockImplementation((path, args, options) => {
|
||||
console.log(args, options.listeners.stdout)
|
||||
|
||||
if (args.includes('version')) {
|
||||
options.listeners.stdout(Buffer.from('2.18'))
|
||||
return 0
|
||||
}
|
||||
|
||||
if (args.includes('rev-parse')) {
|
||||
options.listeners.stdline(Buffer.from('refs/heads/foo'))
|
||||
// If refs/tags/v1 and refs/heads/tags/v1 existed on this repository
|
||||
options.listeners.errline(
|
||||
Buffer.from("error: refname 'tags/v1' is ambiguous")
|
||||
)
|
||||
return 0
|
||||
}
|
||||
|
||||
return 1
|
||||
})
|
||||
jest.spyOn(exec, 'exec').mockImplementation(mockExec)
|
||||
const workingDirectory = 'test'
|
||||
const lfs = false
|
||||
const doSparseCheckout = false
|
||||
git = await commandManager.createCommandManager(
|
||||
workingDirectory,
|
||||
lfs,
|
||||
doSparseCheckout
|
||||
)
|
||||
|
||||
let branches = await git.branchList(false)
|
||||
|
||||
expect(branches).toHaveLength(1)
|
||||
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)
|
||||
)
|
||||
})
|
||||
})
|
@ -281,6 +281,65 @@ describe('git-directory-helper tests', () => {
|
||||
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'
|
||||
it(removesLockFiles, async () => {
|
||||
// Arrange
|
||||
@ -403,6 +462,8 @@ async function setup(testName: string): Promise<void> {
|
||||
branchList: jest.fn(async () => {
|
||||
return []
|
||||
}),
|
||||
sparseCheckout: jest.fn(),
|
||||
sparseCheckoutNonConeMode: jest.fn(),
|
||||
checkout: jest.fn(),
|
||||
checkoutDetach: jest.fn(),
|
||||
config: jest.fn(),
|
||||
@ -423,6 +484,9 @@ async function setup(testName: string): Promise<void> {
|
||||
submoduleForeach: jest.fn(),
|
||||
submoduleSync: jest.fn(),
|
||||
submoduleUpdate: jest.fn(),
|
||||
submoduleStatus: jest.fn(async () => {
|
||||
return true
|
||||
}),
|
||||
tagExists: jest.fn(),
|
||||
tryClean: jest.fn(async () => {
|
||||
return true
|
||||
|
@ -79,7 +79,12 @@ describe('input-helper tests', () => {
|
||||
expect(settings.clean).toBe(true)
|
||||
expect(settings.commit).toBeTruthy()
|
||||
expect(settings.commit).toBe('1234567890123456789012345678901234567890')
|
||||
expect(settings.filter).toBe(undefined)
|
||||
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')
|
||||
|
16
__test__/verify-fetch-filter.sh
Executable file
16
__test__/verify-fetch-filter.sh
Executable file
@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Verify .git folder
|
||||
if [ ! -d "./fetch-filter/.git" ]; then
|
||||
echo "Expected ./fetch-filter/.git folder to exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify .git/config contains partialclonefilter
|
||||
|
||||
CLONE_FILTER=$(git -C fetch-filter config --local --get remote.origin.partialclonefilter)
|
||||
|
||||
if [ "$CLONE_FILTER" != "blob:none" ]; then
|
||||
echo "Expected ./fetch-filter/.git/config to have 'remote.origin.partialclonefilter' set to 'blob:none'"
|
||||
exit 1
|
||||
fi
|
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/bash
|
||||
|
||||
# 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/bash
|
||||
|
||||
# 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
|
22
action.yml
22
action.yml
@ -53,9 +53,29 @@ inputs:
|
||||
clean:
|
||||
description: 'Whether to execute `git clean -ffdx && git reset --hard HEAD` before fetching'
|
||||
default: true
|
||||
filter:
|
||||
description: >
|
||||
Partially clone against a given filter.
|
||||
Overrides sparse-checkout if set.
|
||||
default: null
|
||||
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:
|
||||
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
|
||||
@ -75,6 +95,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
|
||||
|
@ -181,7 +181,7 @@ GITHUB_WORKSPACE=/home/runner/work/foo/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.
|
||||
|
||||
@ -287,4 +287,4 @@ Note:
|
||||
- Update samples to consume `actions/checkout@v2`
|
||||
- Job containers now require git in the PATH for checkout, otherwise fallback to REST API
|
||||
- Minimum git version 2.18
|
||||
- Update problem matcher logic regarding source file verification (runner)
|
||||
- Update problem matcher logic regarding source file verification (runner)
|
||||
|
46390
dist/index.js
vendored
46390
dist/index.js
vendored
File diff suppressed because one or more lines are too long
16856
package-lock.json
generated
16856
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "checkout",
|
||||
"version": "3.2.0",
|
||||
"version": "4.1.0",
|
||||
"description": "checkout action",
|
||||
"main": "lib/main.js",
|
||||
"scripts": {
|
||||
@ -30,18 +30,18 @@
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.10.0",
|
||||
"@actions/exec": "^1.0.1",
|
||||
"@actions/github": "^2.2.0",
|
||||
"@actions/io": "^1.1.2",
|
||||
"@actions/github": "^5.0.0",
|
||||
"@actions/io": "^1.1.3",
|
||||
"@actions/tool-cache": "^1.1.2",
|
||||
"uuid": "^3.3.3"
|
||||
},
|
||||
"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",
|
||||
"@zeit/ncc": "^0.20.5",
|
||||
"@vercel/ncc": "^0.36.1",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-plugin-github": "^4.3.2",
|
||||
"eslint-plugin-jest": "^25.7.0",
|
||||
@ -52,4 +52,4 @@
|
||||
"ts-jest": "^27.0.7",
|
||||
"typescript": "^4.4.4"
|
||||
}
|
||||
}
|
||||
}
|
@ -247,7 +247,7 @@ class GitAuthHelper {
|
||||
if (this.settings.sshKnownHosts) {
|
||||
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`)
|
||||
stateHelper.setSshKnownHostsPath(this.sshKnownHostsPath)
|
||||
await fs.promises.writeFile(this.sshKnownHostsPath, knownHosts)
|
||||
|
@ -1,5 +1,6 @@
|
||||
import * as core from '@actions/core'
|
||||
import * as exec from '@actions/exec'
|
||||
import * as fs from 'fs'
|
||||
import * as fshelper from './fs-helper'
|
||||
import * as io from '@actions/io'
|
||||
import * as path from 'path'
|
||||
@ -16,6 +17,8 @@ export interface IGitCommandManager {
|
||||
branchDelete(remote: boolean, branch: string): Promise<void>
|
||||
branchExists(remote: boolean, pattern: string): Promise<boolean>
|
||||
branchList(remote: boolean): Promise<string[]>
|
||||
sparseCheckout(sparseCheckout: string[]): Promise<void>
|
||||
sparseCheckoutNonConeMode(sparseCheckout: string[]): Promise<void>
|
||||
checkout(ref: string, startPoint: string): Promise<void>
|
||||
checkoutDetach(): Promise<void>
|
||||
config(
|
||||
@ -25,7 +28,15 @@ export interface IGitCommandManager {
|
||||
add?: boolean
|
||||
): Promise<void>
|
||||
configExists(configKey: string, globalConfig?: boolean): Promise<boolean>
|
||||
fetch(refSpec: string[], fetchDepth?: number): Promise<void>
|
||||
fetch(
|
||||
refSpec: string[],
|
||||
options: {
|
||||
filter?: string
|
||||
fetchDepth?: number
|
||||
fetchTags?: boolean
|
||||
showProgress?: boolean
|
||||
}
|
||||
): Promise<void>
|
||||
getDefaultBranch(repositoryUrl: string): Promise<string>
|
||||
getWorkingDirectory(): string
|
||||
init(): Promise<void>
|
||||
@ -41,6 +52,7 @@ export interface IGitCommandManager {
|
||||
submoduleForeach(command: string, recursive: boolean): Promise<string>
|
||||
submoduleSync(recursive: boolean): Promise<void>
|
||||
submoduleUpdate(fetchDepth: number, recursive: boolean): Promise<void>
|
||||
submoduleStatus(): Promise<boolean>
|
||||
tagExists(pattern: string): Promise<boolean>
|
||||
tryClean(): Promise<boolean>
|
||||
tryConfigUnset(configKey: string, globalConfig?: boolean): Promise<boolean>
|
||||
@ -51,9 +63,14 @@ export interface IGitCommandManager {
|
||||
|
||||
export async function createCommandManager(
|
||||
workingDirectory: string,
|
||||
lfs: boolean
|
||||
lfs: boolean,
|
||||
doSparseCheckout: boolean
|
||||
): Promise<IGitCommandManager> {
|
||||
return await GitCommandManager.createCommandManager(workingDirectory, lfs)
|
||||
return await GitCommandManager.createCommandManager(
|
||||
workingDirectory,
|
||||
lfs,
|
||||
doSparseCheckout
|
||||
)
|
||||
}
|
||||
|
||||
class GitCommandManager {
|
||||
@ -63,6 +80,7 @@ class GitCommandManager {
|
||||
}
|
||||
private gitPath = ''
|
||||
private lfs = false
|
||||
private doSparseCheckout = false
|
||||
private workingDirectory = ''
|
||||
|
||||
// Private constructor; use createCommandManager()
|
||||
@ -94,8 +112,11 @@ class GitCommandManager {
|
||||
|
||||
// Note, this implementation uses "rev-parse --symbolic-full-name" because the output from
|
||||
// "branch --list" is more difficult when in a detached HEAD state.
|
||||
// Note, this implementation uses "rev-parse --symbolic-full-name" because there is a bug
|
||||
// in Git 2.18 that causes "rev-parse --symbolic" to output symbolic full names.
|
||||
|
||||
// TODO(https://github.com/actions/checkout/issues/786): this implementation uses
|
||||
// "rev-parse --symbolic-full-name" because there is a bug
|
||||
// in Git 2.18 that causes "rev-parse --symbolic" to output symbolic full names. When
|
||||
// 2.18 is no longer supported, we can switch back to --symbolic.
|
||||
|
||||
const args = ['rev-parse', '--symbolic-full-name']
|
||||
if (remote) {
|
||||
@ -104,24 +125,73 @@ class GitCommandManager {
|
||||
args.push('--branches')
|
||||
}
|
||||
|
||||
const output = await this.execGit(args)
|
||||
const stderr: string[] = []
|
||||
const errline: string[] = []
|
||||
const stdout: string[] = []
|
||||
const stdline: string[] = []
|
||||
|
||||
for (let branch of output.stdout.trim().split('\n')) {
|
||||
branch = branch.trim()
|
||||
if (branch) {
|
||||
if (branch.startsWith('refs/heads/')) {
|
||||
branch = branch.substr('refs/heads/'.length)
|
||||
} else if (branch.startsWith('refs/remotes/')) {
|
||||
branch = branch.substr('refs/remotes/'.length)
|
||||
}
|
||||
|
||||
result.push(branch)
|
||||
const listeners = {
|
||||
stderr: (data: Buffer) => {
|
||||
stderr.push(data.toString())
|
||||
},
|
||||
errline: (data: Buffer) => {
|
||||
errline.push(data.toString())
|
||||
},
|
||||
stdout: (data: Buffer) => {
|
||||
stdout.push(data.toString())
|
||||
},
|
||||
stdline: (data: Buffer) => {
|
||||
stdline.push(data.toString())
|
||||
}
|
||||
}
|
||||
|
||||
// Suppress the output in order to avoid flooding annotations with innocuous errors.
|
||||
await this.execGit(args, false, true, listeners)
|
||||
|
||||
core.debug(`stderr callback is: ${stderr}`)
|
||||
core.debug(`errline callback is: ${errline}`)
|
||||
core.debug(`stdout callback is: ${stdout}`)
|
||||
core.debug(`stdline callback is: ${stdline}`)
|
||||
|
||||
for (let branch of stdline) {
|
||||
branch = branch.trim()
|
||||
if (!branch) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (branch.startsWith('refs/heads/')) {
|
||||
branch = branch.substring('refs/heads/'.length)
|
||||
} else if (branch.startsWith('refs/remotes/')) {
|
||||
branch = branch.substring('refs/remotes/'.length)
|
||||
}
|
||||
|
||||
result.push(branch)
|
||||
}
|
||||
|
||||
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> {
|
||||
const args = ['checkout', '--progress', '--force']
|
||||
if (startPoint) {
|
||||
@ -170,15 +240,31 @@ class GitCommandManager {
|
||||
return output.exitCode === 0
|
||||
}
|
||||
|
||||
async fetch(refSpec: string[], fetchDepth?: number): Promise<void> {
|
||||
async fetch(
|
||||
refSpec: string[],
|
||||
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')
|
||||
if (fetchDepth && fetchDepth > 0) {
|
||||
args.push(`--depth=${fetchDepth}`)
|
||||
args.push('--prune', '--no-recurse-submodules')
|
||||
if (options.showProgress) {
|
||||
args.push('--progress')
|
||||
}
|
||||
|
||||
if (options.filter) {
|
||||
args.push(`--filter=${options.filter}`)
|
||||
}
|
||||
|
||||
if (options.fetchDepth && options.fetchDepth > 0) {
|
||||
args.push(`--depth=${options.fetchDepth}`)
|
||||
} else if (
|
||||
fshelper.fileExistsSync(
|
||||
path.join(this.workingDirectory, '.git', 'shallow')
|
||||
@ -257,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
|
||||
}
|
||||
@ -326,6 +412,12 @@ class GitCommandManager {
|
||||
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> {
|
||||
const output = await this.execGit(['tag', '--list', pattern])
|
||||
return !!output.stdout.trim()
|
||||
@ -385,17 +477,23 @@ class GitCommandManager {
|
||||
|
||||
static async createCommandManager(
|
||||
workingDirectory: string,
|
||||
lfs: boolean
|
||||
lfs: boolean,
|
||||
doSparseCheckout: boolean
|
||||
): Promise<GitCommandManager> {
|
||||
const result = new GitCommandManager()
|
||||
await result.initializeCommandManager(workingDirectory, lfs)
|
||||
await result.initializeCommandManager(
|
||||
workingDirectory,
|
||||
lfs,
|
||||
doSparseCheckout
|
||||
)
|
||||
return result
|
||||
}
|
||||
|
||||
private async execGit(
|
||||
args: string[],
|
||||
allowAllExitCodes = false,
|
||||
silent = false
|
||||
silent = false,
|
||||
customListeners = {}
|
||||
): Promise<GitOutput> {
|
||||
fshelper.directoryExistsSync(this.workingDirectory, true)
|
||||
|
||||
@ -409,28 +507,36 @@ class GitCommandManager {
|
||||
env[key] = this.gitEnv[key]
|
||||
}
|
||||
|
||||
const stdout: string[] = []
|
||||
const defaultListener = {
|
||||
stdout: (data: Buffer) => {
|
||||
stdout.push(data.toString())
|
||||
}
|
||||
}
|
||||
|
||||
const mergedListeners = {...defaultListener, ...customListeners}
|
||||
|
||||
const stdout: string[] = []
|
||||
const options = {
|
||||
cwd: this.workingDirectory,
|
||||
env,
|
||||
silent,
|
||||
ignoreReturnCode: allowAllExitCodes,
|
||||
listeners: {
|
||||
stdout: (data: Buffer) => {
|
||||
stdout.push(data.toString())
|
||||
}
|
||||
}
|
||||
listeners: mergedListeners
|
||||
}
|
||||
|
||||
result.exitCode = await exec.exec(`"${this.gitPath}"`, args, options)
|
||||
result.stdout = stdout.join('')
|
||||
|
||||
core.debug(result.exitCode.toString())
|
||||
core.debug(result.stdout)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private async initializeCommandManager(
|
||||
workingDirectory: string,
|
||||
lfs: boolean
|
||||
lfs: boolean,
|
||||
doSparseCheckout: boolean
|
||||
): Promise<void> {
|
||||
this.workingDirectory = workingDirectory
|
||||
|
||||
@ -493,6 +599,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
|
||||
const gitHttpUserAgent = `git/${gitVersion} (github-actions-checkout)`
|
||||
core.debug(`Set git useragent to: ${gitHttpUserAgent}`)
|
||||
|
@ -81,12 +81,18 @@ export async function prepareExistingDirectory(
|
||||
}
|
||||
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
|
||||
if (clean) {
|
||||
core.startGroup('Cleaning the repository')
|
||||
if (!(await git.tryClean())) {
|
||||
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
|
||||
} else if (!(await git.tryReset())) {
|
||||
|
@ -153,23 +153,38 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
|
||||
|
||||
// Fetch
|
||||
core.startGroup('Fetching the repository')
|
||||
const fetchOptions: {
|
||||
filter?: string
|
||||
fetchDepth?: number
|
||||
fetchTags?: boolean
|
||||
showProgress?: boolean
|
||||
} = {}
|
||||
|
||||
if (settings.filter) {
|
||||
fetchOptions.filter = settings.filter
|
||||
} else if (settings.sparseCheckout) {
|
||||
fetchOptions.filter = 'blob:none'
|
||||
}
|
||||
|
||||
if (settings.fetchDepth <= 0) {
|
||||
// Fetch all branches and tags
|
||||
let refSpec = refHelper.getRefSpecForAllHistory(
|
||||
settings.ref,
|
||||
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
|
||||
// commit (push or force push). If so, fetch again with a targeted refspec.
|
||||
if (!(await refHelper.testRef(git, settings.ref, settings.commit))) {
|
||||
refSpec = refHelper.getRefSpec(settings.ref, settings.commit)
|
||||
await git.fetch(refSpec)
|
||||
await git.fetch(refSpec, fetchOptions)
|
||||
}
|
||||
} else {
|
||||
fetchOptions.fetchDepth = settings.fetchDepth
|
||||
fetchOptions.fetchTags = settings.fetchTags
|
||||
const refSpec = refHelper.getRefSpec(settings.ref, settings.commit)
|
||||
await git.fetch(refSpec, settings.fetchDepth)
|
||||
await git.fetch(refSpec, fetchOptions)
|
||||
}
|
||||
core.endGroup()
|
||||
|
||||
@ -185,12 +200,24 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
|
||||
// LFS fetch
|
||||
// Explicit lfs-fetch to avoid slow checkout (fetches one lfs object at a time).
|
||||
// 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')
|
||||
await git.lfsFetch(checkoutInfo.startPoint || checkoutInfo.ref)
|
||||
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
|
||||
core.startGroup('Checking out the ref')
|
||||
await git.checkout(checkoutInfo.ref, checkoutInfo.startPoint)
|
||||
@ -261,7 +288,11 @@ export async function cleanup(repositoryPath: string): Promise<void> {
|
||||
|
||||
let git: IGitCommandManager
|
||||
try {
|
||||
git = await gitCommandManager.createCommandManager(repositoryPath, false)
|
||||
git = await gitCommandManager.createCommandManager(
|
||||
repositoryPath,
|
||||
false,
|
||||
false
|
||||
)
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
@ -297,7 +328,8 @@ async function getGitCommandManager(
|
||||
try {
|
||||
return await gitCommandManager.createCommandManager(
|
||||
settings.repositoryPath,
|
||||
settings.lfs
|
||||
settings.lfs,
|
||||
settings.sparseCheckout != null
|
||||
)
|
||||
} catch (err) {
|
||||
// Git is required for LFS
|
||||
|
@ -29,11 +29,36 @@ export interface IGitSourceSettings {
|
||||
*/
|
||||
clean: boolean
|
||||
|
||||
/**
|
||||
* The filter determining which objects to include
|
||||
*/
|
||||
filter: string | undefined
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
|
@ -1,12 +1,13 @@
|
||||
import * as assert from 'assert'
|
||||
import * as core from '@actions/core'
|
||||
import * as fs from 'fs'
|
||||
import * as github from '@actions/github'
|
||||
import * as io from '@actions/io'
|
||||
import * as path from 'path'
|
||||
import * as retryHelper from './retry-helper'
|
||||
import * as toolCache from '@actions/tool-cache'
|
||||
import {default as uuid} from 'uuid/v4'
|
||||
import {getOctokit, Octokit} from './octokit-provider'
|
||||
import {getServerApiUrl} from './url-helper'
|
||||
|
||||
const IS_WINDOWS = process.platform === 'win32'
|
||||
|
||||
@ -84,11 +85,13 @@ export async function getDefaultBranch(
|
||||
): Promise<string> {
|
||||
return await retryHelper.execute(async () => {
|
||||
core.info('Retrieving the default branch name')
|
||||
const octokit = getOctokit(authToken, {baseUrl: baseUrl})
|
||||
const octokit = github.getOctokit(authToken, {
|
||||
baseUrl: getServerApiUrl(baseUrl)
|
||||
})
|
||||
let result: string
|
||||
try {
|
||||
// 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
|
||||
assert.ok(result, 'default_branch cannot be empty')
|
||||
} catch (err) {
|
||||
@ -125,19 +128,16 @@ async function downloadArchive(
|
||||
commit: string,
|
||||
baseUrl?: string
|
||||
): Promise<Buffer> {
|
||||
const octokit = getOctokit(authToken, {baseUrl: baseUrl})
|
||||
const params: Octokit.ReposGetArchiveLinkParams = {
|
||||
const octokit = github.getOctokit(authToken, {
|
||||
baseUrl: getServerApiUrl(baseUrl)
|
||||
})
|
||||
const download = IS_WINDOWS
|
||||
? octokit.rest.repos.downloadZipballArchive
|
||||
: octokit.rest.repos.downloadTarballArchive
|
||||
const response = await download({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
archive_format: IS_WINDOWS ? 'zipball' : 'tarball',
|
||||
ref: commit || ref
|
||||
}
|
||||
const response = await octokit.repos.getArchiveLink(params)
|
||||
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
|
||||
})
|
||||
return Buffer.from(response.data as ArrayBuffer) // response.data is ArrayBuffer
|
||||
}
|
||||
|
@ -82,6 +82,25 @@ export async function getInputs(): Promise<IGitSourceSettings> {
|
||||
result.clean = (core.getInput('clean') || 'true').toUpperCase() === 'TRUE'
|
||||
core.debug(`clean = ${result.clean}`)
|
||||
|
||||
// Filter
|
||||
const filter = core.getInput('filter')
|
||||
if (filter) {
|
||||
result.filter = filter
|
||||
}
|
||||
|
||||
core.debug(`filter = ${result.filter}`)
|
||||
|
||||
// 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
|
||||
result.fetchDepth = Math.floor(Number(core.getInput('fetch-depth') || '1'))
|
||||
if (isNaN(result.fetchDepth) || result.fetchDepth < 0) {
|
||||
@ -89,6 +108,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}`)
|
||||
|
@ -120,7 +120,7 @@ function updateUsage(
|
||||
}
|
||||
|
||||
updateUsage(
|
||||
'actions/checkout@v3',
|
||||
'actions/checkout@v4',
|
||||
path.join(__dirname, '..', '..', 'action.yml'),
|
||||
path.join(__dirname, '..', '..', 'README.md')
|
||||
)
|
||||
|
@ -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 * as core from '@actions/core'
|
||||
import * as github from '@actions/github'
|
||||
import {getOctokit} from './octokit-provider'
|
||||
import {isGhes} from './url-helper'
|
||||
import {getServerApiUrl, isGhes} from './url-helper'
|
||||
|
||||
export const tagsRefSpec = '+refs/tags/*:refs/tags/*'
|
||||
|
||||
@ -245,15 +244,18 @@ export async function checkCommitInfo(
|
||||
core.debug(
|
||||
`Expected head sha ${expectedHeadSha}; actual head sha ${actualHeadSha}`
|
||||
)
|
||||
const octokit = getOctokit(token, {
|
||||
baseUrl: baseUrl,
|
||||
const octokit = github.getOctokit(token, {
|
||||
baseUrl: getServerApiUrl(baseUrl),
|
||||
userAgent: `actions-checkout-tracepoint/1.0 (code=STALE_MERGE;owner=${repositoryOwner};repo=${repositoryName};pr=${fromPayload(
|
||||
'number'
|
||||
)};run_id=${
|
||||
process.env['GITHUB_RUN_ID']
|
||||
};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) {
|
||||
core.debug(
|
||||
|
@ -47,7 +47,7 @@ export function setSshKnownHostsPath(sshKnownHostsPath: string) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the sef-safe-directory input so the POST action can retrieve the value.
|
||||
* Save the set-safe-directory input so the POST action can retrieve the value.
|
||||
*/
|
||||
export function setSafeDirectory() {
|
||||
core.saveState('setSafeDirectory', 'true')
|
||||
|
Loading…
Reference in New Issue
Block a user