Compare commits
43 Commits
v1.1.0
...
users/eric
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c455122937 | ||
|
|
605b7eb961 | ||
|
|
036772999d | ||
|
|
46054cf00b | ||
|
|
85a425b582 | ||
|
|
9a3a9ade82 | ||
|
|
b2e6b7ed13 | ||
|
|
80602fafba | ||
|
|
b4626ce19c | ||
|
|
422dc45671 | ||
|
|
204620207c | ||
|
|
f219062370 | ||
|
|
096e927750 | ||
|
|
f858c22e96 | ||
|
|
77904fd431 | ||
|
|
06218e4404 | ||
|
|
61fd8fd0c7 | ||
|
|
f95f2a3856 | ||
|
|
f90c7b395d | ||
|
|
090d9c9dfd | ||
|
|
db41740e12 | ||
|
|
bc50a995b8 | ||
|
|
dfd70d4a2d | ||
|
|
ae525b2262 | ||
|
|
f466b96953 | ||
|
|
c85684db76 | ||
|
|
299dd5064e | ||
|
|
722adc63f1 | ||
|
|
3537747199 | ||
|
|
a6747255bd | ||
|
|
c170eefc26 | ||
|
|
a572f640b0 | ||
|
|
cab31617d8 | ||
|
|
5881116d18 | ||
|
|
7990b10a0c | ||
|
|
01a434328a | ||
|
|
4817b449b0 | ||
|
|
689bf84be4 | ||
|
|
cc70598ce8 | ||
|
|
8461dbfed3 | ||
|
|
e347bba93b | ||
|
|
50fbc622fc | ||
|
|
e8bd1dffb6 |
3
.eslintignore
Normal file
3
.eslintignore
Normal file
@@ -0,0 +1,3 @@
|
||||
dist/
|
||||
lib/
|
||||
node_modules/
|
||||
58
.eslintrc.json
Normal file
58
.eslintrc.json
Normal file
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"plugins": ["jest", "@typescript-eslint"],
|
||||
"extends": ["plugin:github/es6"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 9,
|
||||
"sourceType": "module",
|
||||
"project": "./tsconfig.json"
|
||||
},
|
||||
"rules": {
|
||||
"eslint-comments/no-use": "off",
|
||||
"import/no-namespace": "off",
|
||||
"no-unused-vars": "off",
|
||||
"@typescript-eslint/no-unused-vars": "error",
|
||||
"@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}],
|
||||
"@typescript-eslint/no-require-imports": "error",
|
||||
"@typescript-eslint/array-type": "error",
|
||||
"@typescript-eslint/await-thenable": "error",
|
||||
"@typescript-eslint/ban-ts-ignore": "error",
|
||||
"camelcase": "off",
|
||||
"@typescript-eslint/camelcase": "error",
|
||||
"@typescript-eslint/class-name-casing": "error",
|
||||
"@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}],
|
||||
"@typescript-eslint/func-call-spacing": ["error", "never"],
|
||||
"@typescript-eslint/generic-type-naming": ["error", "^[A-Z][A-Za-z]*$"],
|
||||
"@typescript-eslint/no-array-constructor": "error",
|
||||
"@typescript-eslint/no-empty-interface": "error",
|
||||
"@typescript-eslint/no-explicit-any": "error",
|
||||
"@typescript-eslint/no-extraneous-class": "error",
|
||||
"@typescript-eslint/no-for-in-array": "error",
|
||||
"@typescript-eslint/no-inferrable-types": "error",
|
||||
"@typescript-eslint/no-misused-new": "error",
|
||||
"@typescript-eslint/no-namespace": "error",
|
||||
"@typescript-eslint/no-non-null-assertion": "warn",
|
||||
"@typescript-eslint/no-object-literal-type-assertion": "error",
|
||||
"@typescript-eslint/no-unnecessary-qualifier": "error",
|
||||
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
||||
"@typescript-eslint/no-useless-constructor": "error",
|
||||
"@typescript-eslint/no-var-requires": "error",
|
||||
"@typescript-eslint/prefer-for-of": "warn",
|
||||
"@typescript-eslint/prefer-function-type": "warn",
|
||||
"@typescript-eslint/prefer-includes": "error",
|
||||
"@typescript-eslint/prefer-interface": "error",
|
||||
"@typescript-eslint/prefer-string-starts-ends-with": "error",
|
||||
"@typescript-eslint/promise-function-async": "error",
|
||||
"@typescript-eslint/require-array-sort-compare": "error",
|
||||
"@typescript-eslint/restrict-plus-operands": "error",
|
||||
"semi": "off",
|
||||
"@typescript-eslint/semi": ["error", "never"],
|
||||
"@typescript-eslint/type-annotation-spacing": "error",
|
||||
"@typescript-eslint/unbound-method": "error"
|
||||
},
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true,
|
||||
"jest/globals": true
|
||||
}
|
||||
}
|
||||
203
.github/workflows/test.yml
vendored
203
.github/workflows/test.yml
vendored
@@ -1,18 +1,207 @@
|
||||
name: "test-local"
|
||||
name: Build and Test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- 'releases/*'
|
||||
- releases/*
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 12.x
|
||||
- uses: actions/checkout@v2
|
||||
- run: npm ci
|
||||
- run: npm run build
|
||||
- run: npm run format-check
|
||||
- run: npm run lint
|
||||
- run: npm test
|
||||
- name: Verify no unstaged changes
|
||||
run: __test__/verify-no-unstaged-changes.sh
|
||||
|
||||
test:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [windows-latest, ubuntu-latest, macOS-latest]
|
||||
runs-on: ${{ matrix.os }}
|
||||
runs-on: [ubuntu-latest, macos-latest, windows-latest]
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: ./
|
||||
- run: git ls-remote --tags origin
|
||||
# Clone this repo
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Basic checkout
|
||||
- name: Checkout basic
|
||||
uses: ./
|
||||
with:
|
||||
ref: test-data/v2/basic
|
||||
path: basic
|
||||
- name: Verify basic
|
||||
shell: bash
|
||||
run: __test__/verify-basic.sh
|
||||
|
||||
# Clean
|
||||
- name: Modify work tree
|
||||
shell: bash
|
||||
run: __test__/modify-work-tree.sh
|
||||
- name: Checkout clean
|
||||
uses: ./
|
||||
with:
|
||||
ref: test-data/v2/basic
|
||||
path: basic
|
||||
- name: Verify clean
|
||||
shell: bash
|
||||
run: __test__/verify-clean.sh
|
||||
|
||||
# Side by side
|
||||
- name: Checkout side by side 1
|
||||
uses: ./
|
||||
with:
|
||||
ref: test-data/v2/side-by-side-1
|
||||
path: side-by-side-1
|
||||
- name: Checkout side by side 2
|
||||
uses: ./
|
||||
with:
|
||||
ref: test-data/v2/side-by-side-2
|
||||
path: side-by-side-2
|
||||
- name: Verify side by side
|
||||
shell: bash
|
||||
run: __test__/verify-side-by-side.sh
|
||||
|
||||
# LFS
|
||||
- name: Checkout LFS
|
||||
uses: ./
|
||||
with:
|
||||
repository: actions/checkout # hardcoded, otherwise doesn't work from a fork
|
||||
ref: test-data/v2/lfs
|
||||
path: lfs
|
||||
lfs: true
|
||||
- name: Verify LFS
|
||||
shell: bash
|
||||
run: __test__/verify-lfs.sh
|
||||
|
||||
# Submodules false
|
||||
- name: Checkout submodules false
|
||||
uses: ./
|
||||
with:
|
||||
ref: test-data/v2/submodule-ssh-url
|
||||
path: submodules-false
|
||||
- name: Verify submodules false
|
||||
run: __test__/verify-submodules-false.sh
|
||||
|
||||
# Submodules one level
|
||||
- name: Checkout submodules true
|
||||
uses: ./
|
||||
with:
|
||||
ref: test-data/v2/submodule-ssh-url
|
||||
path: submodules-true
|
||||
submodules: true
|
||||
- name: Verify submodules true
|
||||
run: __test__/verify-submodules-true.sh
|
||||
|
||||
# Submodules recursive
|
||||
- name: Checkout submodules recursive
|
||||
uses: ./
|
||||
with:
|
||||
ref: test-data/v2/submodule-ssh-url
|
||||
path: submodules-recursive
|
||||
submodules: recursive
|
||||
- name: Verify submodules recursive
|
||||
run: __test__/verify-submodules-recursive.sh
|
||||
|
||||
# Basic checkout using REST API
|
||||
- name: Remove basic
|
||||
if: runner.os != 'windows'
|
||||
run: rm -rf basic
|
||||
- name: Remove basic (Windows)
|
||||
if: runner.os == 'windows'
|
||||
shell: cmd
|
||||
run: rmdir /s /q basic
|
||||
- name: Override git version
|
||||
if: runner.os != 'windows'
|
||||
run: __test__/override-git-version.sh
|
||||
- name: Override git version (Windows)
|
||||
if: runner.os == 'windows'
|
||||
run: __test__\\override-git-version.cmd
|
||||
- name: Checkout basic using REST API
|
||||
uses: ./
|
||||
with:
|
||||
ref: test-data/v2/basic
|
||||
path: basic
|
||||
- name: Verify basic
|
||||
run: __test__/verify-basic.sh --archive
|
||||
|
||||
test-proxy:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: alpine/git:latest
|
||||
options: --dns 127.0.0.1
|
||||
services:
|
||||
squid-proxy:
|
||||
image: datadog/squid:latest
|
||||
ports:
|
||||
- 3128:3128
|
||||
env:
|
||||
https_proxy: http://squid-proxy:3128
|
||||
steps:
|
||||
# Clone this repo
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Basic checkout using git
|
||||
- name: Checkout basic
|
||||
uses: ./
|
||||
with:
|
||||
ref: test-data/v2/basic
|
||||
path: basic
|
||||
- name: Verify basic
|
||||
run: __test__/verify-basic.sh
|
||||
|
||||
# Basic checkout using REST API
|
||||
- name: Remove basic
|
||||
run: rm -rf basic
|
||||
- name: Override git version
|
||||
run: __test__/override-git-version.sh
|
||||
- name: Basic checkout using REST API
|
||||
uses: ./
|
||||
with:
|
||||
ref: test-data/v2/basic
|
||||
path: basic
|
||||
- name: Verify basic
|
||||
run: __test__/verify-basic.sh --archive
|
||||
|
||||
test-bypass-proxy:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
https_proxy: http://no-such-proxy:3128
|
||||
no_proxy: api.github.com,github.com
|
||||
steps:
|
||||
# Clone this repo
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
# Basic checkout using git
|
||||
- name: Checkout basic
|
||||
uses: ./
|
||||
with:
|
||||
ref: test-data/v2/basic
|
||||
path: basic
|
||||
- name: Verify basic
|
||||
run: __test__/verify-basic.sh
|
||||
- name: Remove basic
|
||||
run: rm -rf basic
|
||||
|
||||
# Basic checkout using REST API
|
||||
- name: Override git version
|
||||
run: __test__/override-git-version.sh
|
||||
- name: Checkout basic using REST API
|
||||
uses: ./
|
||||
with:
|
||||
ref: test-data/v2/basic
|
||||
path: basic
|
||||
- name: Verify basic
|
||||
run: __test__/verify-basic.sh --archive
|
||||
|
||||
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
__test__/_temp
|
||||
lib/
|
||||
node_modules/
|
||||
3
.prettierignore
Normal file
3
.prettierignore
Normal file
@@ -0,0 +1,3 @@
|
||||
dist/
|
||||
lib/
|
||||
node_modules/
|
||||
11
.prettierrc.json
Normal file
11
.prettierrc.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"printWidth": 80,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"bracketSpacing": false,
|
||||
"arrowParens": "avoid",
|
||||
"parser": "typescript"
|
||||
}
|
||||
23
CHANGELOG.md
Normal file
23
CHANGELOG.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Changelog
|
||||
|
||||
## v2 (beta)
|
||||
|
||||
- Improved fetch performance
|
||||
- The default behavior now fetches only the SHA being checked-out
|
||||
- Script authenticated git commands
|
||||
- Persists `with.token` in the local git config
|
||||
- Enables your scripts to run authenticated git commands
|
||||
- Post-job cleanup removes the token
|
||||
- Coming soon: Opt out by setting `with.persist-credentials` to `false`
|
||||
- Creates a local branch
|
||||
- No longer detached HEAD when checking out a branch
|
||||
- A local branch is created with the corresponding upstream branch set
|
||||
- Improved layout
|
||||
- `with.path` is always relative to `github.workspace`
|
||||
- Aligns better with container actions, where `github.workspace` gets mapped in
|
||||
- Removed input `submodules`
|
||||
|
||||
|
||||
## v1
|
||||
|
||||
Refer [here](https://github.com/actions/checkout/blob/v1/CHANGELOG.md) for the V1 changelog
|
||||
247
README.md
247
README.md
@@ -2,63 +2,248 @@
|
||||
<a href="https://github.com/actions/checkout"><img alt="GitHub Actions status" src="https://github.com/actions/checkout/workflows/test-local/badge.svg"></a>
|
||||
</p>
|
||||
|
||||
# Checkout
|
||||
# Checkout V2
|
||||
|
||||
This action checks out your repository to `$GITHUB_WORKSPACE`, so that your workflow can access the contents of your repository.
|
||||
This action checks-out your repository under `$GITHUB_WORKSPACE`, so your workflow can access it.
|
||||
|
||||
By default, this is equivalent to running `git fetch` and `git checkout $GITHUB_SHA`, so that you'll always have your repo contents at the version that triggered the workflow.
|
||||
See [here](https://help.github.com/en/articles/events-that-trigger-workflows) to learn what `$GITHUB_SHA` is for different kinds of events.
|
||||
Only a single commit is fetched by default, for the ref/SHA that triggered the workflow. Set `fetch-depth` to fetch more history. Refer [here](https://help.github.com/en/articles/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.
|
||||
|
||||
When Git 2.18 or higher is not in your PATH, falls back to the REST API to download the files.
|
||||
|
||||
# What's new
|
||||
|
||||
- Improved performance
|
||||
- Fetches only a single commit by default
|
||||
- Script authenticated git commands
|
||||
- Auth token persisted in the local git config
|
||||
- Creates a local branch
|
||||
- No longer detached HEAD when checking out a branch
|
||||
- Improved layout
|
||||
- The input `path` is always relative to $GITHUB_WORKSPACE
|
||||
- Aligns better with container actions, where $GITHUB_WORKSPACE gets mapped in
|
||||
- Fallback to REST API download
|
||||
- When Git 2.18 or higher is not in the PATH, the REST API will be used to download the files
|
||||
- When using a job container, the container's PATH is used
|
||||
- Removed input `submodules`
|
||||
|
||||
Refer [here](https://github.com/actions/checkout/blob/v1/README.md) for previous versions.
|
||||
|
||||
# Usage
|
||||
|
||||
See [action.yml](action.yml)
|
||||
<!-- start usage -->
|
||||
```yaml
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
# Repository name with owner. For example, actions/checkout
|
||||
# Default: ${{ github.repository }}
|
||||
repository: ''
|
||||
|
||||
Basic:
|
||||
# The branch, tag or SHA to checkout. When checking out the repository that
|
||||
# triggered a workflow, this defaults to the reference or SHA for that event.
|
||||
# Otherwise, defaults to `master`.
|
||||
ref: ''
|
||||
|
||||
# Personal access token (PAT) used to fetch the repository. The PAT is configured
|
||||
# with the local git config, which enables your scripts to run authenticated git
|
||||
# commands. The post-job step removes the PAT.
|
||||
#
|
||||
# We recommend using a service account with the least permissions necessary. Also
|
||||
# when generating a new PAT, select the least scopes necessary.
|
||||
#
|
||||
# [Learn more about creating and using encrypted secrets](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets)
|
||||
#
|
||||
# Default: ${{ github.token }}
|
||||
token: ''
|
||||
|
||||
# SSH key used to fetch the repository. The SSH key is configured with the local
|
||||
# git config, which enables your scripts to run authenticated git commands. The
|
||||
# post-job step removes the SSH key.
|
||||
#
|
||||
# We recommend using a service account with the least permissions necessary.
|
||||
#
|
||||
# [Learn more about creating and using encrypted secrets](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets)
|
||||
ssh-key: ''
|
||||
|
||||
# Known hosts in addition to the user and global host key database. The public SSH
|
||||
# keys for a host may be obtained using the utility `ssh-keyscan`. For example,
|
||||
# `ssh-keyscan github.com`. The public key for github.com is always implicitly
|
||||
# added.
|
||||
ssh-known-hosts: ''
|
||||
|
||||
# Whether to perform strict host key checking. When true, adds the options
|
||||
# `StrictHostKeyChecking=yes` and `CheckHostIP=no` to the SSH command line. Use
|
||||
# the input `ssh-known-hosts` to configure additional hosts.
|
||||
# Default: true
|
||||
ssh-strict: ''
|
||||
|
||||
# Whether to configure the token or SSH key with the local git config
|
||||
# Default: true
|
||||
persist-credentials: ''
|
||||
|
||||
# Relative path under $GITHUB_WORKSPACE to place the repository
|
||||
path: ''
|
||||
|
||||
# Whether to execute `git clean -ffdx && git reset --hard HEAD` before fetching
|
||||
# Default: true
|
||||
clean: ''
|
||||
|
||||
# Number of commits to fetch. 0 indicates all history.
|
||||
# Default: 1
|
||||
fetch-depth: ''
|
||||
|
||||
# Whether to download Git-LFS files
|
||||
# Default: false
|
||||
lfs: ''
|
||||
|
||||
# Whether to checkout submodules: `true` to checkout submodules or `recursive` to
|
||||
# recursively checkout submodules.
|
||||
#
|
||||
# When the `ssh-key` input is not provided, SSH URLs beginning with
|
||||
# `git@github.com:` are converted to HTTPS.
|
||||
#
|
||||
# Default: false
|
||||
submodules: ''
|
||||
```
|
||||
<!-- end usage -->
|
||||
|
||||
# Scenarios
|
||||
|
||||
- [Checkout a different branch](#Checkout-a-different-branch)
|
||||
- [Checkout HEAD^](#Checkout-HEAD)
|
||||
- [Checkout multiple repos (side by side)](#Checkout-multiple-repos-side-by-side)
|
||||
- [Checkout multiple repos (nested)](#Checkout-multiple-repos-nested)
|
||||
- [Checkout multiple repos (private)](#Checkout-multiple-repos-private)
|
||||
- [Checkout pull request HEAD commit instead of merge commit](#Checkout-pull-request-HEAD-commit-instead-of-merge-commit)
|
||||
- [Checkout pull request on closed event](#Checkout-pull-request-on-closed-event)
|
||||
- [Checkout submodules](#Checkout-submodules)
|
||||
- [Fetch all tags](#Fetch-all-tags)
|
||||
- [Fetch all branches](#Fetch-all-branches)
|
||||
- [Fetch all history for all tags and branches](#Fetch-all-history-for-all-tags-and-branches)
|
||||
|
||||
## Checkout a different branch
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/setup-node@v1
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
node-version: 10.x
|
||||
- run: npm install
|
||||
- run: npm test
|
||||
ref: my-branch
|
||||
```
|
||||
|
||||
By default, the branch or tag ref that triggered the workflow will be checked out, `${{ github.token }}` will be used for any Git server authentication. If you wish to check out a different branch, a different repository or use different token to checkout, specify that using `with.ref`, `with.repository` and `with.token`:
|
||||
## Checkout HEAD^
|
||||
|
||||
Checkout different branch from the workflow repository:
|
||||
```yaml
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: some-branch
|
||||
fetch-depth: 2
|
||||
- run: git checkout HEAD^
|
||||
```
|
||||
|
||||
Checkout different private repository:
|
||||
## Checkout multiple repos (side by side)
|
||||
|
||||
```yaml
|
||||
- uses: actions/checkout@v1
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: myAccount/myRepository
|
||||
ref: refs/heads/release
|
||||
token: ${{ secrets.GitHub_PAT }} // `GitHub_PAT` is a secret contains your PAT.
|
||||
path: main
|
||||
|
||||
- name: Checkout tools repo
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: my-org/my-tools
|
||||
path: my-tools
|
||||
```
|
||||
|
||||
Checkout private submodules:
|
||||
## Checkout multiple repos (nested)
|
||||
|
||||
```yaml
|
||||
- uses: actions/checkout@v1
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Checkout tools repo
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
token: ${{ secrets.GitHub_PAT }} // `GitHub_PAT` is a secret contains your PAT.
|
||||
repository: my-org/my-tools
|
||||
path: my-tools
|
||||
```
|
||||
> - `with.token` will be used as `Basic` authentication header for https requests talk to https://github.com from `git(.exe)`, ensure those private submodules are configured via `https` not `ssh`.
|
||||
> - `${{ github.token }}` only has permission to the workflow triggering repository. If the repository contains any submodules that comes from private repository, you will have to add your PAT as secret and use the secret in `with.token` to make `checkout` action work.
|
||||
|
||||
For more details, see [Contexts and expression syntax for GitHub Actions](https://help.github.com/en/articles/contexts-and-expression-syntax-for-github-actions) and [Creating and using secrets (encrypted variables)](https://help.github.com/en/articles/virtual-environments-for-github-actions#creating-and-using-secrets-encrypted-variables)
|
||||
## Checkout multiple repos (private)
|
||||
|
||||
# Changelog
|
||||
```yaml
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: main
|
||||
|
||||
## v1.1.0 (unreleased)
|
||||
- Persist `with.token` or `${{ github.token }}` into checkout repository's git config as `http.https://github.com/.extraheader=AUTHORIZATION: basic ***` to better support scripting git
|
||||
- name: Checkout private tools
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: my-org/my-private-tools
|
||||
token: ${{ secrets.GitHub_PAT }} # `GitHub_PAT` is a secret that contains your PAT
|
||||
path: my-tools
|
||||
```
|
||||
|
||||
> - `${{ github.token }}` is scoped to the current repository, so if you want to checkout a different repository that is private you will need to provide your own [PAT](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line).
|
||||
|
||||
|
||||
## Checkout pull request HEAD commit instead of merge commit
|
||||
|
||||
```yaml
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
```
|
||||
|
||||
## Checkout pull request on closed event
|
||||
|
||||
```yaml
|
||||
on:
|
||||
pull_request:
|
||||
branches: [master]
|
||||
types: [opened, synchronize, closed]
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
```
|
||||
|
||||
## Checkout submodules
|
||||
|
||||
```yaml
|
||||
- uses: actions/checkout@v2
|
||||
- name: Checkout submodules
|
||||
shell: bash
|
||||
run: |
|
||||
# If your submodules are configured to use SSH instead of HTTPS please uncomment the following line
|
||||
# git config --global url."https://github.com/".insteadOf "git@github.com:"
|
||||
auth_header="$(git config --local --get http.https://github.com/.extraheader)"
|
||||
git submodule sync --recursive
|
||||
git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1
|
||||
```
|
||||
|
||||
## Fetch all tags
|
||||
|
||||
```yaml
|
||||
- uses: actions/checkout@v2
|
||||
- run: git fetch --depth=1 origin +refs/tags/*:refs/tags/*
|
||||
```
|
||||
|
||||
## Fetch all branches
|
||||
|
||||
```yaml
|
||||
- uses: actions/checkout@v2
|
||||
- run: |
|
||||
git fetch --no-tags --prune --depth=1 origin +refs/heads/*:refs/remotes/origin/*
|
||||
```
|
||||
|
||||
## Fetch all history for all tags and branches
|
||||
|
||||
```yaml
|
||||
- uses: actions/checkout@v2
|
||||
- run: |
|
||||
git fetch --prune --unshallow
|
||||
```
|
||||
|
||||
# License
|
||||
|
||||
|
||||
801
__test__/git-auth-helper.test.ts
Normal file
801
__test__/git-auth-helper.test.ts
Normal file
File diff suppressed because it is too large
Load Diff
425
__test__/git-directory-helper.test.ts
Normal file
425
__test__/git-directory-helper.test.ts
Normal file
File diff suppressed because it is too large
Load Diff
45
__test__/git-version.test.ts
Normal file
45
__test__/git-version.test.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import {GitVersion} from '../lib/git-version'
|
||||
|
||||
describe('git-version tests', () => {
|
||||
it('basics', async () => {
|
||||
let version = new GitVersion('')
|
||||
expect(version.isValid()).toBeFalsy()
|
||||
|
||||
version = new GitVersion('asdf')
|
||||
expect(version.isValid()).toBeFalsy()
|
||||
|
||||
version = new GitVersion('1.2')
|
||||
expect(version.isValid()).toBeTruthy()
|
||||
expect(version.toString()).toBe('1.2')
|
||||
|
||||
version = new GitVersion('1.2.3')
|
||||
expect(version.isValid()).toBeTruthy()
|
||||
expect(version.toString()).toBe('1.2.3')
|
||||
})
|
||||
|
||||
it('check minimum', async () => {
|
||||
let version = new GitVersion('4.5')
|
||||
expect(version.checkMinimum(new GitVersion('3.6'))).toBeTruthy()
|
||||
expect(version.checkMinimum(new GitVersion('3.6.7'))).toBeTruthy()
|
||||
expect(version.checkMinimum(new GitVersion('4.4'))).toBeTruthy()
|
||||
expect(version.checkMinimum(new GitVersion('4.5'))).toBeTruthy()
|
||||
expect(version.checkMinimum(new GitVersion('4.5.0'))).toBeTruthy()
|
||||
expect(version.checkMinimum(new GitVersion('4.6'))).toBeFalsy()
|
||||
expect(version.checkMinimum(new GitVersion('4.6.0'))).toBeFalsy()
|
||||
expect(version.checkMinimum(new GitVersion('5.1'))).toBeFalsy()
|
||||
expect(version.checkMinimum(new GitVersion('5.1.2'))).toBeFalsy()
|
||||
|
||||
version = new GitVersion('4.5.6')
|
||||
expect(version.checkMinimum(new GitVersion('3.6'))).toBeTruthy()
|
||||
expect(version.checkMinimum(new GitVersion('3.6.7'))).toBeTruthy()
|
||||
expect(version.checkMinimum(new GitVersion('4.4'))).toBeTruthy()
|
||||
expect(version.checkMinimum(new GitVersion('4.5'))).toBeTruthy()
|
||||
expect(version.checkMinimum(new GitVersion('4.5.5'))).toBeTruthy()
|
||||
expect(version.checkMinimum(new GitVersion('4.5.6'))).toBeTruthy()
|
||||
expect(version.checkMinimum(new GitVersion('4.5.7'))).toBeFalsy()
|
||||
expect(version.checkMinimum(new GitVersion('4.6'))).toBeFalsy()
|
||||
expect(version.checkMinimum(new GitVersion('4.6.0'))).toBeFalsy()
|
||||
expect(version.checkMinimum(new GitVersion('5.1'))).toBeFalsy()
|
||||
expect(version.checkMinimum(new GitVersion('5.1.2'))).toBeFalsy()
|
||||
})
|
||||
})
|
||||
133
__test__/input-helper.test.ts
Normal file
133
__test__/input-helper.test.ts
Normal file
@@ -0,0 +1,133 @@
|
||||
import * as assert from 'assert'
|
||||
import * as core from '@actions/core'
|
||||
import * as fsHelper from '../lib/fs-helper'
|
||||
import * as github from '@actions/github'
|
||||
import * as inputHelper from '../lib/input-helper'
|
||||
import * as path from 'path'
|
||||
import {IGitSourceSettings} from '../lib/git-source-settings'
|
||||
|
||||
const originalGitHubWorkspace = process.env['GITHUB_WORKSPACE']
|
||||
const gitHubWorkspace = path.resolve('/checkout-tests/workspace')
|
||||
|
||||
// Inputs for mock @actions/core
|
||||
let inputs = {} as any
|
||||
|
||||
// Shallow clone original @actions/github context
|
||||
let originalContext = {...github.context}
|
||||
|
||||
describe('input-helper tests', () => {
|
||||
beforeAll(() => {
|
||||
// Mock getInput
|
||||
jest.spyOn(core, 'getInput').mockImplementation((name: string) => {
|
||||
return inputs[name]
|
||||
})
|
||||
|
||||
// Mock error/warning/info/debug
|
||||
jest.spyOn(core, 'error').mockImplementation(jest.fn())
|
||||
jest.spyOn(core, 'warning').mockImplementation(jest.fn())
|
||||
jest.spyOn(core, 'info').mockImplementation(jest.fn())
|
||||
jest.spyOn(core, 'debug').mockImplementation(jest.fn())
|
||||
|
||||
// Mock github context
|
||||
jest.spyOn(github.context, 'repo', 'get').mockImplementation(() => {
|
||||
return {
|
||||
owner: 'some-owner',
|
||||
repo: 'some-repo'
|
||||
}
|
||||
})
|
||||
github.context.ref = 'refs/heads/some-ref'
|
||||
github.context.sha = '1234567890123456789012345678901234567890'
|
||||
|
||||
// Mock ./fs-helper directoryExistsSync()
|
||||
jest
|
||||
.spyOn(fsHelper, 'directoryExistsSync')
|
||||
.mockImplementation((path: string) => path == gitHubWorkspace)
|
||||
|
||||
// GitHub workspace
|
||||
process.env['GITHUB_WORKSPACE'] = gitHubWorkspace
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
// Reset inputs
|
||||
inputs = {}
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
// Restore GitHub workspace
|
||||
delete process.env['GITHUB_WORKSPACE']
|
||||
if (originalGitHubWorkspace) {
|
||||
process.env['GITHUB_WORKSPACE'] = originalGitHubWorkspace
|
||||
}
|
||||
|
||||
// Restore @actions/github context
|
||||
github.context.ref = originalContext.ref
|
||||
github.context.sha = originalContext.sha
|
||||
|
||||
// Restore
|
||||
jest.restoreAllMocks()
|
||||
})
|
||||
|
||||
it('sets defaults', () => {
|
||||
const settings: IGitSourceSettings = inputHelper.getInputs()
|
||||
expect(settings).toBeTruthy()
|
||||
expect(settings.authToken).toBeFalsy()
|
||||
expect(settings.clean).toBe(true)
|
||||
expect(settings.commit).toBeTruthy()
|
||||
expect(settings.commit).toBe('1234567890123456789012345678901234567890')
|
||||
expect(settings.fetchDepth).toBe(1)
|
||||
expect(settings.lfs).toBe(false)
|
||||
expect(settings.ref).toBe('refs/heads/some-ref')
|
||||
expect(settings.repositoryName).toBe('some-repo')
|
||||
expect(settings.repositoryOwner).toBe('some-owner')
|
||||
expect(settings.repositoryPath).toBe(gitHubWorkspace)
|
||||
})
|
||||
|
||||
it('qualifies ref', () => {
|
||||
let originalRef = github.context.ref
|
||||
try {
|
||||
github.context.ref = 'some-unqualified-ref'
|
||||
const settings: IGitSourceSettings = inputHelper.getInputs()
|
||||
expect(settings).toBeTruthy()
|
||||
expect(settings.commit).toBe('1234567890123456789012345678901234567890')
|
||||
expect(settings.ref).toBe('refs/heads/some-unqualified-ref')
|
||||
} finally {
|
||||
github.context.ref = originalRef
|
||||
}
|
||||
})
|
||||
|
||||
it('requires qualified repo', () => {
|
||||
inputs.repository = 'some-unqualified-repo'
|
||||
assert.throws(() => {
|
||||
inputHelper.getInputs()
|
||||
}, /Invalid repository 'some-unqualified-repo'/)
|
||||
})
|
||||
|
||||
it('roots path', () => {
|
||||
inputs.path = 'some-directory/some-subdirectory'
|
||||
const settings: IGitSourceSettings = inputHelper.getInputs()
|
||||
expect(settings.repositoryPath).toBe(
|
||||
path.join(gitHubWorkspace, 'some-directory', 'some-subdirectory')
|
||||
)
|
||||
})
|
||||
|
||||
it('sets correct default ref/sha for other repo', () => {
|
||||
inputs.repository = 'some-owner/some-other-repo'
|
||||
const settings: IGitSourceSettings = inputHelper.getInputs()
|
||||
expect(settings.ref).toBe('refs/heads/master')
|
||||
expect(settings.commit).toBeFalsy()
|
||||
})
|
||||
|
||||
it('sets ref to empty when explicit sha', () => {
|
||||
inputs.ref = '1111111111222222222233333333334444444444'
|
||||
const settings: IGitSourceSettings = inputHelper.getInputs()
|
||||
expect(settings.ref).toBeFalsy()
|
||||
expect(settings.commit).toBe('1111111111222222222233333333334444444444')
|
||||
})
|
||||
|
||||
it('sets sha to empty when explicit ref', () => {
|
||||
inputs.ref = 'refs/heads/some-other-ref'
|
||||
const settings: IGitSourceSettings = inputHelper.getInputs()
|
||||
expect(settings.ref).toBe('refs/heads/some-other-ref')
|
||||
expect(settings.commit).toBeFalsy()
|
||||
})
|
||||
})
|
||||
10
__test__/modify-work-tree.sh
Executable file
10
__test__/modify-work-tree.sh
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ ! -f "./basic/basic-file.txt" ]; then
|
||||
echo "Expected basic file does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo hello >> ./basic/basic-file.txt
|
||||
echo hello >> ./basic/new-file.txt
|
||||
git -C ./basic status
|
||||
6
__test__/override-git-version.cmd
Executable file
6
__test__/override-git-version.cmd
Executable file
@@ -0,0 +1,6 @@
|
||||
|
||||
mkdir override-git-version
|
||||
cd override-git-version
|
||||
echo @echo override git version 1.2.3 > git.cmd
|
||||
echo ::add-path::%CD%
|
||||
cd ..
|
||||
9
__test__/override-git-version.sh
Executable file
9
__test__/override-git-version.sh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
mkdir override-git-version
|
||||
cd override-git-version
|
||||
echo "#!/bin/sh" > git
|
||||
echo "echo override git version 1.2.3" >> git
|
||||
chmod +x git
|
||||
echo "::add-path::$(pwd)"
|
||||
cd ..
|
||||
168
__test__/ref-helper.test.ts
Normal file
168
__test__/ref-helper.test.ts
Normal file
@@ -0,0 +1,168 @@
|
||||
import * as assert from 'assert'
|
||||
import * as refHelper from '../lib/ref-helper'
|
||||
import {IGitCommandManager} from '../lib/git-command-manager'
|
||||
|
||||
const commit = '1234567890123456789012345678901234567890'
|
||||
let git: IGitCommandManager
|
||||
|
||||
describe('ref-helper tests', () => {
|
||||
beforeEach(() => {
|
||||
git = ({} as unknown) as IGitCommandManager
|
||||
})
|
||||
|
||||
it('getCheckoutInfo requires git', async () => {
|
||||
const git = (null as unknown) as IGitCommandManager
|
||||
try {
|
||||
await refHelper.getCheckoutInfo(git, 'refs/heads/my/branch', commit)
|
||||
throw new Error('Should not reach here')
|
||||
} catch (err) {
|
||||
expect(err.message).toBe('Arg git cannot be empty')
|
||||
}
|
||||
})
|
||||
|
||||
it('getCheckoutInfo requires ref or commit', async () => {
|
||||
try {
|
||||
await refHelper.getCheckoutInfo(git, '', '')
|
||||
throw new Error('Should not reach here')
|
||||
} catch (err) {
|
||||
expect(err.message).toBe('Args ref and commit cannot both be empty')
|
||||
}
|
||||
})
|
||||
|
||||
it('getCheckoutInfo sha only', async () => {
|
||||
const checkoutInfo = await refHelper.getCheckoutInfo(git, '', commit)
|
||||
expect(checkoutInfo.ref).toBe(commit)
|
||||
expect(checkoutInfo.startPoint).toBeFalsy()
|
||||
})
|
||||
|
||||
it('getCheckoutInfo refs/heads/', async () => {
|
||||
const checkoutInfo = await refHelper.getCheckoutInfo(
|
||||
git,
|
||||
'refs/heads/my/branch',
|
||||
commit
|
||||
)
|
||||
expect(checkoutInfo.ref).toBe('my/branch')
|
||||
expect(checkoutInfo.startPoint).toBe('refs/remotes/origin/my/branch')
|
||||
})
|
||||
|
||||
it('getCheckoutInfo refs/pull/', async () => {
|
||||
const checkoutInfo = await refHelper.getCheckoutInfo(
|
||||
git,
|
||||
'refs/pull/123/merge',
|
||||
commit
|
||||
)
|
||||
expect(checkoutInfo.ref).toBe('refs/remotes/pull/123/merge')
|
||||
expect(checkoutInfo.startPoint).toBeFalsy()
|
||||
})
|
||||
|
||||
it('getCheckoutInfo refs/tags/', async () => {
|
||||
const checkoutInfo = await refHelper.getCheckoutInfo(
|
||||
git,
|
||||
'refs/tags/my-tag',
|
||||
commit
|
||||
)
|
||||
expect(checkoutInfo.ref).toBe('refs/tags/my-tag')
|
||||
expect(checkoutInfo.startPoint).toBeFalsy()
|
||||
})
|
||||
|
||||
it('getCheckoutInfo unqualified branch only', async () => {
|
||||
git.branchExists = jest.fn(async (remote: boolean, pattern: string) => {
|
||||
return true
|
||||
})
|
||||
|
||||
const checkoutInfo = await refHelper.getCheckoutInfo(git, 'my/branch', '')
|
||||
|
||||
expect(checkoutInfo.ref).toBe('my/branch')
|
||||
expect(checkoutInfo.startPoint).toBe('refs/remotes/origin/my/branch')
|
||||
})
|
||||
|
||||
it('getCheckoutInfo unqualified tag only', async () => {
|
||||
git.branchExists = jest.fn(async (remote: boolean, pattern: string) => {
|
||||
return false
|
||||
})
|
||||
git.tagExists = jest.fn(async (pattern: string) => {
|
||||
return true
|
||||
})
|
||||
|
||||
const checkoutInfo = await refHelper.getCheckoutInfo(git, 'my-tag', '')
|
||||
|
||||
expect(checkoutInfo.ref).toBe('refs/tags/my-tag')
|
||||
expect(checkoutInfo.startPoint).toBeFalsy()
|
||||
})
|
||||
|
||||
it('getCheckoutInfo unqualified ref only, not a branch or tag', async () => {
|
||||
git.branchExists = jest.fn(async (remote: boolean, pattern: string) => {
|
||||
return false
|
||||
})
|
||||
git.tagExists = jest.fn(async (pattern: string) => {
|
||||
return false
|
||||
})
|
||||
|
||||
try {
|
||||
await refHelper.getCheckoutInfo(git, 'my-ref', '')
|
||||
throw new Error('Should not reach here')
|
||||
} catch (err) {
|
||||
expect(err.message).toBe(
|
||||
"A branch or tag with the name 'my-ref' could not be found"
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
it('getRefSpec requires ref or commit', async () => {
|
||||
assert.throws(
|
||||
() => refHelper.getRefSpec('', ''),
|
||||
/Args ref and commit cannot both be empty/
|
||||
)
|
||||
})
|
||||
|
||||
it('getRefSpec sha + refs/heads/', async () => {
|
||||
const refSpec = refHelper.getRefSpec('refs/heads/my/branch', commit)
|
||||
expect(refSpec.length).toBe(1)
|
||||
expect(refSpec[0]).toBe(`+${commit}:refs/remotes/origin/my/branch`)
|
||||
})
|
||||
|
||||
it('getRefSpec sha + refs/pull/', async () => {
|
||||
const refSpec = refHelper.getRefSpec('refs/pull/123/merge', commit)
|
||||
expect(refSpec.length).toBe(1)
|
||||
expect(refSpec[0]).toBe(`+${commit}:refs/remotes/pull/123/merge`)
|
||||
})
|
||||
|
||||
it('getRefSpec sha + refs/tags/', async () => {
|
||||
const refSpec = refHelper.getRefSpec('refs/tags/my-tag', commit)
|
||||
expect(refSpec.length).toBe(1)
|
||||
expect(refSpec[0]).toBe(`+${commit}:refs/tags/my-tag`)
|
||||
})
|
||||
|
||||
it('getRefSpec sha only', async () => {
|
||||
const refSpec = refHelper.getRefSpec('', commit)
|
||||
expect(refSpec.length).toBe(1)
|
||||
expect(refSpec[0]).toBe(commit)
|
||||
})
|
||||
|
||||
it('getRefSpec unqualified ref only', async () => {
|
||||
const refSpec = refHelper.getRefSpec('my-ref', '')
|
||||
expect(refSpec.length).toBe(2)
|
||||
expect(refSpec[0]).toBe('+refs/heads/my-ref*:refs/remotes/origin/my-ref*')
|
||||
expect(refSpec[1]).toBe('+refs/tags/my-ref*:refs/tags/my-ref*')
|
||||
})
|
||||
|
||||
it('getRefSpec refs/heads/ only', async () => {
|
||||
const refSpec = refHelper.getRefSpec('refs/heads/my/branch', '')
|
||||
expect(refSpec.length).toBe(1)
|
||||
expect(refSpec[0]).toBe(
|
||||
'+refs/heads/my/branch:refs/remotes/origin/my/branch'
|
||||
)
|
||||
})
|
||||
|
||||
it('getRefSpec refs/pull/ only', async () => {
|
||||
const refSpec = refHelper.getRefSpec('refs/pull/123/merge', '')
|
||||
expect(refSpec.length).toBe(1)
|
||||
expect(refSpec[0]).toBe('+refs/pull/123/merge:refs/remotes/pull/123/merge')
|
||||
})
|
||||
|
||||
it('getRefSpec refs/tags/ only', async () => {
|
||||
const refSpec = refHelper.getRefSpec('refs/tags/my-tag', '')
|
||||
expect(refSpec.length).toBe(1)
|
||||
expect(refSpec[0]).toBe('+refs/tags/my-tag:refs/tags/my-tag')
|
||||
})
|
||||
})
|
||||
87
__test__/retry-helper.test.ts
Normal file
87
__test__/retry-helper.test.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import * as core from '@actions/core'
|
||||
import {RetryHelper} from '../lib/retry-helper'
|
||||
|
||||
let info: string[]
|
||||
let retryHelper: any
|
||||
|
||||
describe('retry-helper tests', () => {
|
||||
beforeAll(() => {
|
||||
// Mock @actions/core info()
|
||||
jest.spyOn(core, 'info').mockImplementation((message: string) => {
|
||||
info.push(message)
|
||||
})
|
||||
|
||||
retryHelper = new RetryHelper(3, 0, 0)
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
// Reset info
|
||||
info = []
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
// Restore
|
||||
jest.restoreAllMocks()
|
||||
})
|
||||
|
||||
it('first attempt succeeds', async () => {
|
||||
const actual = await retryHelper.execute(async () => {
|
||||
return 'some result'
|
||||
})
|
||||
expect(actual).toBe('some result')
|
||||
expect(info).toHaveLength(0)
|
||||
})
|
||||
|
||||
it('second attempt succeeds', async () => {
|
||||
let attempts = 0
|
||||
const actual = await retryHelper.execute(() => {
|
||||
if (++attempts == 1) {
|
||||
throw new Error('some error')
|
||||
}
|
||||
|
||||
return Promise.resolve('some result')
|
||||
})
|
||||
expect(attempts).toBe(2)
|
||||
expect(actual).toBe('some result')
|
||||
expect(info).toHaveLength(2)
|
||||
expect(info[0]).toBe('some error')
|
||||
expect(info[1]).toMatch(/Waiting .+ seconds before trying again/)
|
||||
})
|
||||
|
||||
it('third attempt succeeds', async () => {
|
||||
let attempts = 0
|
||||
const actual = await retryHelper.execute(() => {
|
||||
if (++attempts < 3) {
|
||||
throw new Error(`some error ${attempts}`)
|
||||
}
|
||||
|
||||
return Promise.resolve('some result')
|
||||
})
|
||||
expect(attempts).toBe(3)
|
||||
expect(actual).toBe('some result')
|
||||
expect(info).toHaveLength(4)
|
||||
expect(info[0]).toBe('some error 1')
|
||||
expect(info[1]).toMatch(/Waiting .+ seconds before trying again/)
|
||||
expect(info[2]).toBe('some error 2')
|
||||
expect(info[3]).toMatch(/Waiting .+ seconds before trying again/)
|
||||
})
|
||||
|
||||
it('all attempts fail succeeds', async () => {
|
||||
let attempts = 0
|
||||
let error: Error = (null as unknown) as Error
|
||||
try {
|
||||
await retryHelper.execute(() => {
|
||||
throw new Error(`some error ${++attempts}`)
|
||||
})
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
expect(error.message).toBe('some error 3')
|
||||
expect(attempts).toBe(3)
|
||||
expect(info).toHaveLength(4)
|
||||
expect(info[0]).toBe('some error 1')
|
||||
expect(info[1]).toMatch(/Waiting .+ seconds before trying again/)
|
||||
expect(info[2]).toBe('some error 2')
|
||||
expect(info[3]).toMatch(/Waiting .+ seconds before trying again/)
|
||||
})
|
||||
})
|
||||
24
__test__/verify-basic.sh
Executable file
24
__test__/verify-basic.sh
Executable file
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ ! -f "./basic/basic-file.txt" ]; then
|
||||
echo "Expected basic file does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$1" = "--archive" ]; then
|
||||
# Verify no .git folder
|
||||
if [ -d "./basic/.git" ]; then
|
||||
echo "Did not expect ./basic/.git folder to exist"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
# Verify .git folder
|
||||
if [ ! -d "./basic/.git" ]; then
|
||||
echo "Expected ./basic/.git folder to exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verify auth token
|
||||
cd basic
|
||||
git fetch --no-tags --depth=1 origin +refs/heads/master:refs/remotes/origin/master
|
||||
fi
|
||||
13
__test__/verify-clean.sh
Executable file
13
__test__/verify-clean.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ "$(git -C ./basic status --porcelain)" != "" ]]; then
|
||||
echo ----------------------------------------
|
||||
echo git status
|
||||
echo ----------------------------------------
|
||||
git status
|
||||
echo ----------------------------------------
|
||||
echo git diff
|
||||
echo ----------------------------------------
|
||||
git diff
|
||||
exit 1
|
||||
fi
|
||||
11
__test__/verify-lfs.sh
Executable file
11
__test__/verify-lfs.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ ! -f "./lfs/regular-file.txt" ]; then
|
||||
echo "Expected regular file does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "./lfs/lfs-file.bin" ]; then
|
||||
echo "Expected lfs file does not exist"
|
||||
exit 1
|
||||
fi
|
||||
17
__test__/verify-no-unstaged-changes.sh
Executable file
17
__test__/verify-no-unstaged-changes.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ "$(git status --porcelain)" != "" ]]; then
|
||||
echo ----------------------------------------
|
||||
echo git status
|
||||
echo ----------------------------------------
|
||||
git status
|
||||
echo ----------------------------------------
|
||||
echo git diff
|
||||
echo ----------------------------------------
|
||||
git diff
|
||||
echo ----------------------------------------
|
||||
echo Troubleshooting
|
||||
echo ----------------------------------------
|
||||
echo "::error::Unstaged changes detected. Locally try running: git clean -ffdx && npm ci && npm run all"
|
||||
exit 1
|
||||
fi
|
||||
11
__test__/verify-side-by-side.sh
Executable file
11
__test__/verify-side-by-side.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ ! -f "./side-by-side-1/side-by-side-test-file-1.txt" ]; then
|
||||
echo "Expected file 1 does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "./side-by-side-2/side-by-side-test-file-2.txt" ]; then
|
||||
echo "Expected file 2 does not exist"
|
||||
exit 1
|
||||
fi
|
||||
11
__test__/verify-submodules-false.sh
Executable file
11
__test__/verify-submodules-false.sh
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ ! -f "./submodules-false/regular-file.txt" ]; then
|
||||
echo "Expected regular file does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -f "./submodules-false/submodule-level-1/submodule-file.txt" ]; then
|
||||
echo "Unexpected submodule file exists"
|
||||
exit 1
|
||||
fi
|
||||
26
__test__/verify-submodules-recursive.sh
Executable file
26
__test__/verify-submodules-recursive.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ ! -f "./submodules-recursive/regular-file.txt" ]; then
|
||||
echo "Expected regular file does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "./submodules-recursive/submodule-level-1/submodule-file.txt" ]; then
|
||||
echo "Expected submodule file does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "./submodules-recursive/submodule-level-1/submodule-level-2/nested-submodule-file.txt" ]; then
|
||||
echo "Expected nested submodule file does not exists"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Testing persisted credential"
|
||||
pushd ./submodules-recursive/submodule-level-1/submodule-level-2
|
||||
git config --local --name-only --get-regexp http.+extraheader && git fetch
|
||||
if [ "$?" != "0" ]; then
|
||||
echo "Failed to validate persisted credential"
|
||||
popd
|
||||
exit 1
|
||||
fi
|
||||
popd
|
||||
26
__test__/verify-submodules-true.sh
Executable file
26
__test__/verify-submodules-true.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ ! -f "./submodules-true/regular-file.txt" ]; then
|
||||
echo "Expected regular file does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "./submodules-true/submodule-level-1/submodule-file.txt" ]; then
|
||||
echo "Expected submodule file does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -f "./submodules-true/submodule-level-1/submodule-level-2/nested-submodule-file.txt" ]; then
|
||||
echo "Unexpected nested submodule file exists"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Testing persisted credential"
|
||||
pushd ./submodules-true/submodule-level-1
|
||||
git config --local --name-only --get-regexp http.+extraheader && git fetch
|
||||
if [ "$?" != "0" ]; then
|
||||
echo "Failed to validate persisted credential"
|
||||
popd
|
||||
exit 1
|
||||
fi
|
||||
popd
|
||||
83
action.yml
83
action.yml
@@ -1,23 +1,74 @@
|
||||
name: 'Checkout'
|
||||
description: 'Checkout a Git repository.'
|
||||
inputs:
|
||||
description: 'Checkout a Git repository at a particular version'
|
||||
inputs:
|
||||
repository:
|
||||
description: 'Repository name'
|
||||
description: 'Repository name with owner. For example, actions/checkout'
|
||||
default: ${{ github.repository }}
|
||||
ref:
|
||||
description: 'Ref to checkout (SHA, branch, tag)'
|
||||
description: >
|
||||
The branch, tag or SHA to checkout. When checking out the repository that
|
||||
triggered a workflow, this defaults to the reference or SHA for that
|
||||
event. Otherwise, defaults to `master`.
|
||||
token:
|
||||
description: 'Access token for clone repository'
|
||||
clean:
|
||||
description: 'If true, execute `execute git clean -ffdx && git reset --hard HEAD` before fetching'
|
||||
description: >
|
||||
Personal access token (PAT) used to fetch the repository. The PAT is configured
|
||||
with the local git config, which enables your scripts to run authenticated git
|
||||
commands. The post-job step removes the PAT.
|
||||
|
||||
|
||||
We recommend using a service account with the least permissions necessary.
|
||||
Also when generating a new PAT, select the least scopes necessary.
|
||||
|
||||
|
||||
[Learn more about creating and using encrypted secrets](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets)
|
||||
default: ${{ github.token }}
|
||||
ssh-key:
|
||||
description: >
|
||||
SSH key used to fetch the repository. The SSH key is configured with the local
|
||||
git config, which enables your scripts to run authenticated git commands.
|
||||
The post-job step removes the SSH key.
|
||||
|
||||
|
||||
We recommend using a service account with the least permissions necessary.
|
||||
|
||||
|
||||
[Learn more about creating and using
|
||||
encrypted secrets](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets)
|
||||
ssh-known-hosts:
|
||||
description: >
|
||||
Known hosts in addition to the user and global host key database. The public
|
||||
SSH keys for a host may be obtained using the utility `ssh-keyscan`. For example,
|
||||
`ssh-keyscan github.com`. The public key for github.com is always implicitly added.
|
||||
ssh-strict:
|
||||
description: >
|
||||
Whether to perform strict host key checking. When true, adds the options `StrictHostKeyChecking=yes`
|
||||
and `CheckHostIP=no` to the SSH command line. Use the input `ssh-known-hosts` to
|
||||
configure additional hosts.
|
||||
default: true
|
||||
persist-credentials:
|
||||
description: 'Whether to configure the token or SSH key with the local git config'
|
||||
default: true
|
||||
submodules:
|
||||
description: 'Whether to include submodules: false to exclude submodules, true to include only one level of submodules, or recursive to recursively clone submodules; defaults to false'
|
||||
lfs:
|
||||
description: 'Whether to download Git-LFS files; defaults to false'
|
||||
fetch-depth:
|
||||
description: 'The depth of commits to ask Git to fetch; defaults to no limit'
|
||||
path:
|
||||
description: 'Optional path to check out source code'
|
||||
description: 'Relative path under $GITHUB_WORKSPACE to place the repository'
|
||||
clean:
|
||||
description: 'Whether to execute `git clean -ffdx && git reset --hard HEAD` before fetching'
|
||||
default: true
|
||||
fetch-depth:
|
||||
description: 'Number of commits to fetch. 0 indicates all history.'
|
||||
default: 1
|
||||
lfs:
|
||||
description: 'Whether to download Git-LFS files'
|
||||
default: false
|
||||
submodules:
|
||||
description: >
|
||||
Whether to checkout submodules: `true` to checkout submodules or `recursive` to
|
||||
recursively checkout submodules.
|
||||
|
||||
|
||||
When the `ssh-key` input is not provided, SSH URLs beginning with `git@github.com:` are
|
||||
converted to HTTPS.
|
||||
default: false
|
||||
runs:
|
||||
# Plugins live on the runner and are only available to a certain set of first party actions.
|
||||
plugin: 'checkoutV1_1'
|
||||
using: node12
|
||||
main: dist/index.js
|
||||
post: dist/index.js
|
||||
|
||||
271
adrs/0153-checkout-v2.md
Normal file
271
adrs/0153-checkout-v2.md
Normal file
@@ -0,0 +1,271 @@
|
||||
# ADR 0153: Checkout v2
|
||||
|
||||
**Date**: 2019-10-21
|
||||
|
||||
**Status**: Accepted
|
||||
|
||||
## Context
|
||||
|
||||
This ADR details the behavior for `actions/checkout@v2`.
|
||||
|
||||
The new action will be written in typescript. We are moving away from runner-plugin actions.
|
||||
|
||||
We want to take this opportunity to make behavioral changes, from v1. This document is scoped to those differences.
|
||||
|
||||
## Decision
|
||||
|
||||
### Inputs
|
||||
|
||||
```yaml
|
||||
repository:
|
||||
description: 'Repository name with owner. For example, actions/checkout'
|
||||
default: ${{ github.repository }}
|
||||
ref:
|
||||
description: >
|
||||
The branch, tag or SHA to checkout. When checking out the repository that
|
||||
triggered a workflow, this defaults to the reference or SHA for that
|
||||
event. Otherwise, defaults to `master`.
|
||||
token:
|
||||
description: >
|
||||
Personal access token (PAT) used to fetch the repository. The PAT is configured
|
||||
with the local git config, which enables your scripts to run authenticated git
|
||||
commands. The post-job step removes the PAT. [Learn more about creating and using
|
||||
encrypted secrets](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets)
|
||||
default: ${{ github.token }}
|
||||
ssh-key:
|
||||
description: >
|
||||
SSH key used to fetch the repository. SSH key is configured with the local
|
||||
git config, which enables your scripts to run authenticated git commands.
|
||||
The post-job step removes the SSH key. [Learn more about creating and using
|
||||
encrypted secrets](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets)
|
||||
ssh-known-hosts:
|
||||
description: >
|
||||
Known hosts in addition to the user and global host key database. The public
|
||||
SSH keys for a host may be obtained using the utility `ssh-keyscan`. For example,
|
||||
`ssh-keyscan github.com`. The public key for github.com is always implicitly added.
|
||||
ssh-strict:
|
||||
description: 'Whether to perform strict host key checking'
|
||||
default: true
|
||||
persist-credentials:
|
||||
description: 'Whether to configure the token or SSH key with the local git config'
|
||||
default: true
|
||||
path:
|
||||
description: 'Relative path under $GITHUB_WORKSPACE to place the repository'
|
||||
clean:
|
||||
description: 'Whether to execute `git clean -ffdx && git reset --hard HEAD` before fetching'
|
||||
default: true
|
||||
fetch-depth:
|
||||
description: 'Number of commits to fetch. 0 indicates all history.'
|
||||
default: 1
|
||||
lfs:
|
||||
description: 'Whether to download Git-LFS files'
|
||||
default: false
|
||||
submodules:
|
||||
description: >
|
||||
Whether to checkout submodules: `true` to checkout submodules or `recursive` to
|
||||
recursively checkout submodules.
|
||||
default: 'false'
|
||||
```
|
||||
|
||||
Note:
|
||||
- SSH support is new
|
||||
- `persist-credentials` is new
|
||||
- `path` behavior is different (refer [below](#path) for details)
|
||||
|
||||
### Fallback to GitHub API
|
||||
|
||||
When a sufficient version of git is not in the PATH, fallback to the [web API](https://developer.github.com/v3/repos/contents/#get-archive-link) to download a tarball/zipball.
|
||||
|
||||
Note:
|
||||
- LFS files are not included in the archive. Therefore fail if LFS is set to true.
|
||||
- Submodules are also not included in the archive.
|
||||
|
||||
### Persist credentials
|
||||
|
||||
The credentials will be persisted on disk. This will allow users to script authenticated git commands, like `git fetch`.
|
||||
|
||||
A post script will remove the credentials (cleanup for self-hosted).
|
||||
|
||||
Users may opt-out by specifying `persist-credentials: false`
|
||||
|
||||
Note:
|
||||
- Users scripting `git commit` may need to set the username and email. The service does not provide any reasonable default value. Users can add `git config user.name <NAME>` and `git config user.email <EMAIL>`. We will document this guidance.
|
||||
|
||||
#### PAT
|
||||
|
||||
When using the `${{github.token}}` or a PAT, the token will be persisted in the local git config. The config key `http.https://github.com/.extraheader` enables an auth header to be specified on all authenticated commands `AUTHORIZATION: basic <BASE64_U:P>`.
|
||||
|
||||
Note:
|
||||
- The auth header is scoped to all of github `http.https://github.com/.extraheader`
|
||||
- Additional public remotes also just work.
|
||||
- If users want to authenticate to an additional private remote, they should provide the `token` input.
|
||||
|
||||
#### SSH key
|
||||
|
||||
The SSH key will be written to disk under the `$RUNNER_TEMP` directory. The SSH key will
|
||||
be removed by the action's post-job hook. Additionally, RUNNER_TEMP is cleared by the
|
||||
runner between jobs.
|
||||
|
||||
The SSH key must be written with strict file permissions. The SSH client requires the file
|
||||
to be read/write for the user, and not accessible by others.
|
||||
|
||||
The user host key database (`~/.ssh/known_hosts`) will be copied to a unique file under
|
||||
`$RUNNER_TEMP`. And values from the input `ssh-known-hosts` will be added to the file.
|
||||
|
||||
The SSH command will be overridden for the local git config:
|
||||
|
||||
```sh
|
||||
git config core.sshCommand 'ssh -i "$RUNNER_TEMP/path-to-ssh-key" -o StrictHostKeyChecking=yes -o CheckHostIP=no -o "UserKnownHostsFile=$RUNNER_TEMP/path-to-known-hosts"'
|
||||
```
|
||||
|
||||
When the input `ssh-strict` is set to `false`, the options `CheckHostIP` and `StrictHostKeyChecking` will not be overridden.
|
||||
|
||||
Note:
|
||||
- When `ssh-strict` is set to `true` (default), the SSH option `CheckHostIP` can safely be disabled.
|
||||
Strict host checking verifies the server's public key. Therefore, IP verification is unnecessary
|
||||
and noisy. For example:
|
||||
> Warning: Permanently added the RSA host key for IP address '140.82.113.4' to the list of known hosts.
|
||||
- Since GIT_SSH_COMMAND overrides core.sshCommand, temporarily set the env var when fetching the repo. When creds
|
||||
are persisted, core.sshCommand is leveraged to avoid multiple checkout steps stomping over each other.
|
||||
- Modify actions/runner to mount RUNNER_TEMP to enable scripting authenticated git commands from a container action.
|
||||
- Refer [here](https://linux.die.net/man/5/ssh_config) for SSH config details.
|
||||
|
||||
### Fetch behavior
|
||||
|
||||
Fetch only the SHA being built and set depth=1. This significantly reduces the fetch time for large repos.
|
||||
|
||||
If a SHA isn't available (e.g. multi repo), then fetch only the specified ref with depth=1.
|
||||
|
||||
The input `fetch-depth` can be used to control the depth.
|
||||
|
||||
Note:
|
||||
- Fetching a single commit is supported by Git wire protocol version 2. The git client uses protocol version 0 by default. The desired protocol version can be overridden in the git config or on the fetch command line invocation (`-c protocol.version=2`). We will override on the fetch command line, for transparency.
|
||||
- Git client version 2.18+ (released June 2018) is required for wire protocol version 2.
|
||||
|
||||
### Checkout behavior
|
||||
|
||||
For CI, checkout will create a local ref with the upstream set. This allows users to script git as they normally would.
|
||||
|
||||
For PR, continue to checkout detached head. The PR branch is special - the branch and merge commit are created by the server. It doesn't match a users' local workflow.
|
||||
|
||||
Note:
|
||||
- Consider deleting all local refs during cleanup if that helps avoid collisions. More testing required.
|
||||
|
||||
### Path
|
||||
|
||||
For the mainline scenario, the disk-layout behavior remains the same.
|
||||
|
||||
Remember, given the repo `johndoe/foo`, the mainline disk layout looks like:
|
||||
|
||||
```
|
||||
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 no longer changes `github.workspace` to follow wherever the self repo is checked-out.
|
||||
|
||||
These behavioral changes align better with container actions. The [documented filesystem contract](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/virtual-environments-for-github-hosted-runners#docker-container-filesystem) is:
|
||||
|
||||
- `/github/home`
|
||||
- `/github/workspace` - Note: GitHub Actions must be run by the default Docker user (root). Ensure your Dockerfile does not set the USER instruction, otherwise you will not be able to access `GITHUB_WORKSPACE`.
|
||||
- `/github/workflow`
|
||||
|
||||
Note:
|
||||
- The tracking config will not be updated to reflect the path of the workflow repo.
|
||||
- Any existing workflow repo will not be moved when the checkout path changes. In fact some customers want to checkout the workflow repo twice, side by side against different branches.
|
||||
- Actions that need to operate only against the root of the self repo, should expose a `path` input.
|
||||
|
||||
#### Default value for `path` input
|
||||
|
||||
The `path` input will default to `./` which is rooted against `github.workspace`.
|
||||
|
||||
This default fits the mainline scenario well: single checkout
|
||||
|
||||
For multi-checkout, users must specify the `path` input for at least one of the repositories.
|
||||
|
||||
Note:
|
||||
- An alternative is for the self repo to default to `./` and other repos default to `<REPO_NAME>`. However nested layout is an atypical git layout and therefore is not a good default. Users should supply the path info.
|
||||
|
||||
#### Example - Nested layout
|
||||
|
||||
The following example checks-out two repositories and creates a nested layout.
|
||||
|
||||
```yaml
|
||||
# Self repo - Checkout to $GITHUB_WORKSPACE
|
||||
- uses: checkout@v2
|
||||
|
||||
# Other repo - Checkout to $GITHUB_WORKSPACE/myscripts
|
||||
- uses: checkout@v2
|
||||
with:
|
||||
repository: myorg/myscripts
|
||||
path: myscripts
|
||||
```
|
||||
|
||||
#### Example - Side by side layout
|
||||
|
||||
The following example checks-out two repositories and creates a side-by-side layout.
|
||||
|
||||
```yaml
|
||||
# Self repo - Checkout to $GITHUB_WORKSPACE/foo
|
||||
- uses: checkout@v2
|
||||
with:
|
||||
path: foo
|
||||
|
||||
# Other repo - Checkout to $GITHUB_WORKSPACE/myscripts
|
||||
- uses: checkout@v2
|
||||
with:
|
||||
repository: myorg/myscripts
|
||||
path: myscripts
|
||||
```
|
||||
|
||||
#### Path impact to problem matchers
|
||||
|
||||
Problem matchers associate the source files with annotations.
|
||||
|
||||
Today the runner verifies the source file is under the `github.workspace`. Otherwise the source file property is dropped.
|
||||
|
||||
Multi-checkout complicates the matter. However even today submodules may cause this heuristic to be inaccurate.
|
||||
|
||||
A better solution is:
|
||||
|
||||
Given a source file path, walk up the directories until the first `.git/config` is found. Check if it matches the self repo (`url = https://github.com/OWNER/REPO`). If not, drop the source file path.
|
||||
|
||||
### Submodules
|
||||
|
||||
With both PAT and SSH key support, we should be able to provide frictionless support for
|
||||
submodules scenarios: recursive, non-recursive, relative submodule paths.
|
||||
|
||||
When fetching submodules, follow the `fetch-depth` settings.
|
||||
|
||||
Also when fetching submodules, if the `ssh-key` input is not provided then convert SSH URLs to HTTPS: `-c url."https://github.com/".insteadOf "git@github.com:"`
|
||||
|
||||
Credentials will be persisted in the submodules local git config too.
|
||||
|
||||
### Port to typescript
|
||||
|
||||
The checkout action should be a typescript action on the GitHub graph, for the following reasons:
|
||||
- Enables customers to fork the checkout repo and modify
|
||||
- Serves as an example for customers
|
||||
- Demystifies the checkout action manifest
|
||||
- Simplifies the runner
|
||||
- Reduce the amount of runner code to port (if we ever do)
|
||||
|
||||
Note:
|
||||
- This means job-container images will need git in the PATH, for checkout.
|
||||
|
||||
### Branching strategy and release tags
|
||||
|
||||
- Create a servicing branch for V1: `releases/v1`
|
||||
- Merge the changes into `master`
|
||||
- Release using a new tag `preview`
|
||||
- When stable, release using a new tag `v2`
|
||||
|
||||
## Consequences
|
||||
|
||||
- Update the checkout action and readme
|
||||
- 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)
|
||||
17697
dist/index.js
vendored
Normal file
17697
dist/index.js
vendored
Normal file
File diff suppressed because one or more lines are too long
13
dist/problem-matcher.json
vendored
Normal file
13
dist/problem-matcher.json
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "checkout-git",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^(fatal|error): (.*)$",
|
||||
"message": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
11
jest.config.js
Normal file
11
jest.config.js
Normal file
@@ -0,0 +1,11 @@
|
||||
module.exports = {
|
||||
clearMocks: true,
|
||||
moduleFileExtensions: ['js', 'ts'],
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/*.test.ts'],
|
||||
testRunner: 'jest-circus/runner',
|
||||
transform: {
|
||||
'^.+\\.ts$': 'ts-jest'
|
||||
},
|
||||
verbose: true
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user