Compare commits

...

17 Commits

Author SHA1 Message Date
8c9b201842 adr support fetch-refs 2020-02-13 15:54:56 -05:00
f858c22e96 update adr to match current behavior (#154) 2020-02-13 15:26:25 -05:00
77904fd431 Handle submodules with SSH URLs (#140)
* Handle submodules with SSH URLs

This is just a documentation change, explaining how to fix submodules
that are configured to use SSH URLs instead of HTTPS URLs. Spent a while
banging my head on the wall and hope this saves someone else the pain.

This is helpful for teams that use the SSH protocol for local
development so don't want to change the mechanism that pulls in the
submodules. Using `insteadOf` seems a bit nicer than than setting up a
deploy keypair.

* SSH submodules

Co-authored-by: Chris Patterson <chrispat@github.com>
2020-02-13 14:44:37 -05:00
06218e4404 checkout v2 adr (#153) 2020-02-13 14:43:20 -05:00
61fd8fd0c7 switch to spyOn for mocks (#152) 2020-02-13 13:25:46 -05:00
f95f2a3856 Update test.yml 2020-01-27 10:26:27 -05:00
f90c7b395d follow proxy settings (#144) 2020-01-27 10:21:50 -05:00
090d9c9dfd fix ref for pr closed event when a pr is merged (#141) 2020-01-21 14:17:04 -05:00
db41740e12 consume v2 action during build (#131) 2020-01-03 12:49:41 -05:00
bc50a995b8 Add link to doc for creating and using encyrpted secrets (#123) 2020-01-03 12:32:17 -05:00
dfd70d4a2d 2.0.1 (#129) 2020-01-03 11:24:41 -05:00
ae525b2262 fix issue checking detached when git less than 2.22 (#128) 2020-01-03 10:13:01 -05:00
f466b96953 improve summary (#127) 2020-01-02 15:40:10 -05:00
c85684db76 example fetch all history for all tags and branches (#115) 2019-12-16 10:45:02 -05:00
299dd5064e add more scenarios (#112) 2019-12-13 16:39:47 -05:00
722adc63f1 update examples to reference v2 tag (#110) 2019-12-13 00:00:48 -05:00
3537747199 fix ref (#109) 2019-12-12 14:44:19 -05:00
15 changed files with 1550 additions and 146 deletions

View File

@ -11,7 +11,10 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1 # todo: switch to v2
- 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
@ -31,7 +34,7 @@ jobs:
steps:
# Clone this repo
- name: Checkout
uses: actions/checkout@v2-beta
uses: actions/checkout@v2
# Basic checkout
- name: Basic checkout
@ -83,17 +86,92 @@ jobs:
shell: bash
run: __test__/verify-lfs.sh
test-job-container:
runs-on: ubuntu-latest
container: alpine:latest
steps:
# Clone this repo
# todo: after v2-beta contains the latest changes, switch this to "uses: actions/checkout@v2-beta"
- name: Checkout
uses: actions/checkout@a572f640b07e96fc5837b3adfa0e5a2ddd8dae21
# Basic checkout
- name: Basic checkout
# 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: Basic checkout 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: Basic checkout
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: Basic checkout
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: Basic checkout using REST API
uses: ./
with:
ref: test-data/v2/basic

152
README.md
View File

@ -2,31 +2,30 @@
<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 V2 beta
# Checkout V2
This action checks-out your repository under `$GITHUB_WORKSPACE`, so your workflow can access it.
By default, the repository that triggered the workflow is checked-out, for the ref/SHA that triggered the event.
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.
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 fetch performance
- The default behavior now fetches only the commit being checked-out
- Improved performance
- Fetches only a single commit by default
- Script authenticated git commands
- Persists the input `token` in the local git config
- Enables your scripts to run authenticated git commands
- Post-job cleanup removes the token
- Opt out by setting the input `persist-credentials: false`
- Auth token persisted in the local git config
- 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
- 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.
@ -35,7 +34,7 @@ Refer [here](https://github.com/actions/checkout/blob/v1/README.md) for previous
<!-- start usage -->
```yaml
- uses: actions/checkout@v2-beta
- uses: actions/checkout@v2
with:
# Repository name with owner. For example, actions/checkout
# Default: ${{ github.repository }}
@ -48,7 +47,8 @@ Refer [here](https://github.com/actions/checkout/blob/v1/README.md) for previous
# Auth token used to fetch the repository. The token is stored in the local git
# config, which enables your scripts to run authenticated git commands. The
# post-job step removes the token from the git config.
# post-job step removes the token from the git config. [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: ''
@ -73,33 +73,143 @@ Refer [here](https://github.com/actions/checkout/blob/v1/README.md) for previous
```
<!-- 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
- uses: actions/checkout@v2-beta
- uses: actions/checkout@v2
with:
ref: some-branch
ref: my-branch
```
## Checkout a different, private repository
## Checkout HEAD^
```yaml
- uses: actions/checkout@v2-beta
- uses: actions/checkout@v2
with:
repository: myAccount/myRepository
ref: refs/heads/master
fetch-depth: 2
- run: git checkout HEAD^
```
## Checkout multiple repos (side by side)
```yaml
- name: Checkout
uses: actions/checkout@v2
with:
path: main
- name: Checkout tools repo
uses: actions/checkout@v2
with:
repository: my-org/my-tools
path: my-tools
```
## Checkout multiple repos (nested)
```yaml
- name: Checkout
uses: actions/checkout@v2
- name: Checkout tools repo
uses: actions/checkout@v2
with:
repository: my-org/my-tools
path: my-tools
```
## Checkout multiple repos (private)
```yaml
- name: Checkout
uses: actions/checkout@v2
with:
path: main
- 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 another 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 the HEAD commit of a PR, rather than the merge commit
> - `${{ 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-beta
- 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
The scripts and documentation in this project are released under the [MIT License](LICENSE)

View File

@ -1,47 +1,44 @@
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 {ISourceSettings} from '../lib/git-source-provider'
const originalGitHubWorkspace = process.env['GITHUB_WORKSPACE']
const gitHubWorkspace = path.resolve('/checkout-tests/workspace')
// Late bind
let inputHelper: any
// Mock @actions/core
// Inputs for mock @actions/core
let inputs = {} as any
const mockCore = jest.genMockFromModule('@actions/core') as any
mockCore.getInput = (name: string) => {
return inputs[name]
}
// Mock @actions/github
const mockGitHub = jest.genMockFromModule('@actions/github') as any
mockGitHub.context = {
repo: {
owner: 'some-owner',
repo: 'some-repo'
},
ref: 'refs/heads/some-ref',
sha: '1234567890123456789012345678901234567890'
}
// Mock ./fs-helper
const mockFSHelper = jest.genMockFromModule('../lib/fs-helper') as any
mockFSHelper.directoryExistsSync = (path: string) => path == gitHubWorkspace
// Shallow clone original @actions/github context
let originalContext = {...github.context}
describe('input-helper tests', () => {
beforeAll(() => {
// Mock @actions/core getInput()
jest.spyOn(core, 'getInput').mockImplementation((name: string) => {
return inputs[name]
})
// Mock @actions/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
// Mocks
jest.setMock('@actions/core', mockCore)
jest.setMock('@actions/github', mockGitHub)
jest.setMock('../lib/fs-helper', mockFSHelper)
// Now import
inputHelper = require('../lib/input-helper')
})
beforeEach(() => {
@ -50,14 +47,18 @@ describe('input-helper tests', () => {
})
afterAll(() => {
// Reset GitHub workspace
// Restore GitHub workspace
delete process.env['GITHUB_WORKSPACE']
if (originalGitHubWorkspace) {
process.env['GITHUB_WORKSPACE'] = originalGitHubWorkspace
}
// Reset modules
jest.resetModules()
// Restore @actions/github context
github.context.ref = originalContext.ref
github.context.sha = originalContext.sha
// Restore
jest.restoreAllMocks()
})
it('sets defaults', () => {
@ -75,6 +76,19 @@ describe('input-helper tests', () => {
expect(settings.repositoryPath).toBe(gitHubWorkspace)
})
it('qualifies ref', () => {
let originalRef = github.context.ref
try {
github.context.ref = 'some-unqualified-ref'
const settings: ISourceSettings = 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(() => {

View 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 ..

View 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 ..

View File

@ -1,18 +1,17 @@
const mockCore = jest.genMockFromModule('@actions/core') as any
mockCore.info = (message: string) => {
info.push(message)
}
import * as core from '@actions/core'
import {RetryHelper} from '../lib/retry-helper'
let info: string[]
let retryHelper: any
describe('retry-helper tests', () => {
beforeAll(() => {
// Mocks
jest.setMock('@actions/core', mockCore)
// Mock @actions/core info()
jest.spyOn(core, 'info').mockImplementation((message: string) => {
info.push(message)
})
// Now import
const retryHelperModule = require('../lib/retry-helper')
retryHelper = new retryHelperModule.RetryHelper(3, 0, 0)
retryHelper = new RetryHelper(3, 0, 0)
})
beforeEach(() => {
@ -21,8 +20,8 @@ describe('retry-helper tests', () => {
})
afterAll(() => {
// Reset modules
jest.resetModules()
// Restore
jest.restoreAllMocks()
})
it('first attempt succeeds', async () => {

View File

@ -13,7 +13,8 @@ inputs:
description: >
Auth token used to fetch the repository. The token is stored in the local
git config, which enables your scripts to run authenticated git commands.
The post-job step removes the token from the git config.
The post-job step removes the token from the git config. [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 }}
persist-credentials:
description: 'Whether to persist the token in the git config'

215
adrs/0153-checkout-v2.md Normal file
View File

@ -0,0 +1,215 @@
# 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: >
Auth token used to fetch the repository. The token is stored in the local
git config, which enables your scripts to run authenticated git commands.
The post-job step removes the token from the git config. [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 }}
persist-credentials:
description: 'Whether to persist the token in the 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
fetch-refs:
description: >
Additional refs to fetch: `branches`, `tags`, `pr-base`, or `all`.
Combinations are also accepted. For example: `branches, tags`
default: ''
lfs:
description: 'Whether to download Git-LFS files'
default: false
```
Note:
- `fetch-refs` is new
- `persist-credentials` is new
- `path` behavior is different (refer [below](#path) for details)
- `submodules` was removed (error if specified; add later if needed)
### 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. However submodules are not supported by checkout v2 anyway.
### Persist credentials
Persist the token in the git config (http.extraheader). This will allow users to script authenticated git commands, like `git fetch`.
A post script will remove the credentials from the git config (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.
- The auth header (stored in the repo's git config), 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.
- Lines up if we add submodule support in the future. Don't need to worry about calculating relative URLs. Just works, although needs to be persisted in each submodule git config.
- Users opt out of persisted credentials (`persist-credentials: false`), or can script the removal themselves (`git config --unset-all http.https://github.com/.extraheader`).
### 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.
The input `fetch-refs` can be used to fetch additional refs.
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.
### 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)

994
dist/index.js vendored

File diff suppressed because one or more lines are too long

45
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "checkout",
"version": "2.0.0",
"version": "2.0.2",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -15,14 +15,30 @@
"integrity": "sha512-nvFkxwiicvpzNiCBF4wFBDfnBvi7xp/as7LE1hBxBxKG2L29+gkIPBiLKMVORL+Hg3JNf07AKRfl0V5djoypjQ=="
},
"@actions/github": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@actions/github/-/github-2.0.0.tgz",
"integrity": "sha512-sNpZ5dJyJyfJIO5lNYx8r/Gha4Tlm8R0MLO2cBkGdOnAAEn3t1M/MHVcoBhY/VPfjGVe5RNAUPz+6INrViiUPA==",
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@actions/github/-/github-2.1.0.tgz",
"integrity": "sha512-G4ncMlh4pLLAvNgHUYUtpWQ1zPf/VYqmRH9oshxLabdaOOnp7i1hgSgzr2xne2YUaSND3uqemd3YYTIsm2f/KQ==",
"requires": {
"@actions/http-client": "^1.0.3",
"@octokit/graphql": "^4.3.1",
"@octokit/rest": "^16.15.0"
}
},
"@actions/http-client": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.3.tgz",
"integrity": "sha512-wFwh1U4adB/Zsk4cc9kVqaBOHoknhp/pJQk+aWTocbAZWpIl4Zx/At83WFRLXvxB+5HVTWOACM6qjULMZfQSfw==",
"requires": {
"tunnel": "0.0.6"
},
"dependencies": {
"tunnel": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg=="
}
}
},
"@actions/io": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.0.1.tgz",
@ -597,6 +613,14 @@
"@types/yargs": "^13.0.0"
}
},
"@octokit/auth-token": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.4.0.tgz",
"integrity": "sha512-eoOVMjILna7FVQf96iWc3+ZtE/ZT6y8ob8ZzcqKY1ibSQCnu4O/B7pJvzMx5cyZ/RjAff6DAdEb0O0Cjcxidkg==",
"requires": {
"@octokit/types": "^2.0.0"
}
},
"@octokit/endpoint": {
"version": "5.5.1",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-5.5.1.tgz",
@ -643,10 +667,11 @@
}
},
"@octokit/rest": {
"version": "16.35.0",
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-16.35.0.tgz",
"integrity": "sha512-9ShFqYWo0CLoGYhA1FdtdykJuMzS/9H6vSbbQWDX4pWr4p9v+15MsH/wpd/3fIU+tSxylaNO48+PIHqOkBRx3w==",
"version": "16.38.1",
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-16.38.1.tgz",
"integrity": "sha512-zyNFx+/Bd1EXt7LQjfrc6H4wryBQ/oDuZeZhGMBSFr1eMPFDmpEweFQR3R25zjKwBQpDY7L5GQO6A3XSaOfV1w==",
"requires": {
"@octokit/auth-token": "^2.4.0",
"@octokit/request": "^5.2.0",
"@octokit/request-error": "^1.0.2",
"atob-lite": "^2.0.0",
@ -662,9 +687,9 @@
}
},
"@octokit/types": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.0.2.tgz",
"integrity": "sha512-StASIL2lgT3TRjxv17z9pAqbnI7HGu9DrJlg3sEBFfCLaMEqp+O3IQPUF6EZtQ4xkAu2ml6kMBBCtGxjvmtmuQ==",
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.1.1.tgz",
"integrity": "sha512-89LOYH+d/vsbDX785NOfLxTW88GjNd0lWRz1DVPVsZgg9Yett5O+3MOvwo7iHgvUwbFz0mf/yPIjBkUbs4kxoQ==",
"requires": {
"@types/node": ">= 8"
}

View File

@ -1,6 +1,6 @@
{
"name": "checkout",
"version": "2.0.0",
"version": "2.0.2",
"description": "checkout action",
"main": "lib/main.js",
"scripts": {
@ -31,7 +31,7 @@
"dependencies": {
"@actions/core": "^1.1.3",
"@actions/exec": "^1.0.1",
"@actions/github": "^2.0.0",
"@actions/github": "^2.0.2",
"@actions/io": "^1.0.1",
"@actions/tool-cache": "^1.1.2",
"uuid": "^3.3.3"

View File

@ -77,10 +77,12 @@ class GitCommandManager {
async branchList(remote: boolean): Promise<string[]> {
const result: string[] = []
// Note, this implementation uses "rev-parse --symbolic" because the output from
// 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.
const args = ['rev-parse', '--symbolic']
const args = ['rev-parse', '--symbolic-full-name']
if (remote) {
args.push('--remotes=origin')
} else {
@ -92,6 +94,12 @@ class GitCommandManager {
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)
}
}
@ -170,12 +178,12 @@ class GitCommandManager {
}
async isDetached(): Promise<boolean> {
// Note, this implementation uses "branch --show-current" because
// "rev-parse --symbolic-full-name HEAD" can fail on a new repo
// with nothing checked out.
const output = await this.execGit(['branch', '--show-current'])
return output.stdout.trim() === ''
// Note, "branch --show-current" would be simpler but isn't available until Git 2.22
const output = await this.execGit(
['rev-parse', '--symbolic-full-name', '--verify', '--quiet', 'HEAD'],
true
)
return !output.stdout.trim().startsWith('refs/heads/')
}
async lfsFetch(ref: string): Promise<void> {

View File

@ -9,7 +9,8 @@ import * as refHelper from './ref-helper'
import * as stateHelper from './state-helper'
import {IGitCommandManager} from './git-command-manager'
const authConfigKey = `http.https://github.com/.extraheader`
const serverUrl = 'https://github.com/'
const authConfigKey = `http.${serverUrl}.extraheader`
export interface ISourceSettings {
repositoryPath: string
@ -95,7 +96,7 @@ export async function getSource(settings: ISourceSettings): Promise<void> {
await removeGitConfig(git, authConfigKey)
try {
// Config auth token
// Config extraheader
await configureAuthToken(git, settings.authToken)
// LFS install
@ -136,16 +137,21 @@ export async function getSource(settings: ISourceSettings): Promise<void> {
export async function cleanup(repositoryPath: string): Promise<void> {
// Repo exists?
if (!fsHelper.fileExistsSync(path.join(repositoryPath, '.git', 'config'))) {
if (
!repositoryPath ||
!fsHelper.fileExistsSync(path.join(repositoryPath, '.git', 'config'))
) {
return
}
fsHelper.directoryExistsSync(repositoryPath, true)
// Remove the config key
const git = await gitCommandManager.CreateCommandManager(
repositoryPath,
false
)
let git: IGitCommandManager
try {
git = await gitCommandManager.CreateCommandManager(repositoryPath, false)
} catch {
return
}
// Remove extraheader
await removeGitConfig(git, authConfigKey)
}

View File

@ -61,6 +61,12 @@ export function getInputs(): ISourceSettings {
if (isWorkflowRepository) {
result.ref = github.context.ref
result.commit = github.context.sha
// Some events have an unqualifed ref. For example when a PR is merged (pull_request closed event),
// the ref is unqualifed like "master" instead of "refs/heads/master".
if (result.commit && result.ref && !result.ref.startsWith('refs/')) {
result.ref = `refs/heads/${result.ref}`
}
}
if (!result.ref && !result.commit) {

View File

@ -65,9 +65,14 @@ function updateUsage(
let segment: string = description
if (description.length > width) {
segment = description.substr(0, width + 1)
while (!segment.endsWith(' ')) {
while (!segment.endsWith(' ') && segment) {
segment = segment.substr(0, segment.length - 1)
}
// Trimmed too much?
if (segment.length < width * 0.67) {
segment = description
}
} else {
segment = description
}
@ -96,7 +101,7 @@ function updateUsage(
}
updateUsage(
'actions/checkout@v2-beta',
'actions/checkout@v2',
path.join(__dirname, '..', '..', 'action.yml'),
path.join(__dirname, '..', '..', 'README.md')
)