Public Access
1
0
mirror of https://github.com/actions/checkout.git synced 2025-07-15 05:03:50 +00:00

Compare commits

..

2 Commits

Author SHA1 Message Date
d668097b24 . 2021-07-12 11:09:36 -05:00
4edfe9f331 Update main.ts 2021-07-12 11:06:24 -05:00
47 changed files with 4731 additions and 19943 deletions

View File

@ -1,6 +1,6 @@
{ {
"plugins": ["jest", "@typescript-eslint"], "plugins": ["jest", "@typescript-eslint"],
"extends": ["plugin:github/recommended"], "extends": ["plugin:github/es6"],
"parser": "@typescript-eslint/parser", "parser": "@typescript-eslint/parser",
"parserOptions": { "parserOptions": {
"ecmaVersion": 9, "ecmaVersion": 9,
@ -16,9 +16,13 @@
"@typescript-eslint/no-require-imports": "error", "@typescript-eslint/no-require-imports": "error",
"@typescript-eslint/array-type": "error", "@typescript-eslint/array-type": "error",
"@typescript-eslint/await-thenable": "error", "@typescript-eslint/await-thenable": "error",
"@typescript-eslint/ban-ts-ignore": "error",
"camelcase": "off", "camelcase": "off",
"@typescript-eslint/camelcase": "error",
"@typescript-eslint/class-name-casing": "error",
"@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}], "@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}],
"@typescript-eslint/func-call-spacing": ["error", "never"], "@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-array-constructor": "error",
"@typescript-eslint/no-empty-interface": "error", "@typescript-eslint/no-empty-interface": "error",
"@typescript-eslint/no-explicit-any": "error", "@typescript-eslint/no-explicit-any": "error",
@ -29,6 +33,7 @@
"@typescript-eslint/no-misused-new": "error", "@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-namespace": "error", "@typescript-eslint/no-namespace": "error",
"@typescript-eslint/no-non-null-assertion": "warn", "@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-qualifier": "error",
"@typescript-eslint/no-unnecessary-type-assertion": "error", "@typescript-eslint/no-unnecessary-type-assertion": "error",
"@typescript-eslint/no-useless-constructor": "error", "@typescript-eslint/no-useless-constructor": "error",
@ -36,6 +41,7 @@
"@typescript-eslint/prefer-for-of": "warn", "@typescript-eslint/prefer-for-of": "warn",
"@typescript-eslint/prefer-function-type": "warn", "@typescript-eslint/prefer-function-type": "warn",
"@typescript-eslint/prefer-includes": "error", "@typescript-eslint/prefer-includes": "error",
"@typescript-eslint/prefer-interface": "error",
"@typescript-eslint/prefer-string-starts-ends-with": "error", "@typescript-eslint/prefer-string-starts-ends-with": "error",
"@typescript-eslint/promise-function-async": "error", "@typescript-eslint/promise-function-async": "error",
"@typescript-eslint/require-array-sort-compare": "error", "@typescript-eslint/require-array-sort-compare": "error",

View File

@ -1,51 +0,0 @@
# `dist/index.js` is a special file in Actions.
# When you reference an action with `uses:` in a workflow,
# `index.js` is the code that will run.
# For our project, we generate this file through a build process
# from other source files.
# We need to make sure the checked-in `index.js` actually matches what we expect it to be.
name: Check dist
on:
push:
branches:
- main
paths-ignore:
- '**.md'
pull_request:
paths-ignore:
- '**.md'
workflow_dispatch:
jobs:
check-dist:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set Node.js 16.x
uses: actions/setup-node@v1
with:
node-version: 16.x
- name: Install dependencies
run: npm ci
- name: Rebuild the index.js file
run: npm run build
- name: Compare the expected and actual dist/ directories
run: |
if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then
echo "Detected uncommitted changes after build. See status below:"
git diff
exit 1
fi
# If dist/ was different than expected, upload the expected version as an artifact
- uses: actions/upload-artifact@v2
if: ${{ failure() && steps.diff.conclusion == 'failure' }}
with:
name: dist
path: dist/

View File

@ -1,58 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ main ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
schedule:
- cron: '28 9 * * 0'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
- run: npm ci
- run: npm run build
- run: rm -rf dist # We want code scanning to analyze lib instead (individual .js files)
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@ -11,4 +11,10 @@ jobs:
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- run: npm ci - run: npm ci
- run: npm run licensed-check - name: Install licensed
run: |
cd $RUNNER_TEMP
curl -Lfs -o licensed.tar.gz https://github.com/github/licensed/releases/download/2.12.2/licensed-2.12.2-linux-x64.tar.gz
sudo tar -xzf licensed.tar.gz
sudo mv licensed /usr/local/bin/licensed
- run: licensed status

View File

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

1
.gitignore vendored
View File

@ -1,4 +1,3 @@
__test__/_temp __test__/_temp
_temp/
lib/ lib/
node_modules/ node_modules/

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
.licenses/npm/qs.dep.yml generated

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -2,7 +2,7 @@
<a href="https://github.com/actions/checkout"><img alt="GitHub Actions status" src="https://github.com/actions/checkout/workflows/test-local/badge.svg"></a> <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> </p>
# Checkout V3 # Checkout V2
This action checks-out your repository under `$GITHUB_WORKSPACE`, so your workflow can access it. This action checks-out your repository under `$GITHUB_WORKSPACE`, so your workflow can access it.
@ -14,14 +14,27 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
# What's new # What's new
- Updated to the node16 runtime by default - Improved performance
- This requires a minimum [Actions Runner](https://github.com/actions/runner/releases/tag/v2.285.0) version of v2.285.0 to run, which is by default available in GHES 3.4 or later. - Fetches only a single commit by default
- Script authenticated git commands
- Auth token persisted in the local git config
- Supports SSH
- 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
Refer [here](https://github.com/actions/checkout/blob/v1/README.md) for previous versions.
# Usage # Usage
<!-- start usage --> <!-- start usage -->
```yaml ```yaml
- uses: actions/checkout@v3 - uses: actions/checkout@v2
with: with:
# Repository name with owner. For example, actions/checkout # Repository name with owner. For example, actions/checkout
# Default: ${{ github.repository }} # Default: ${{ github.repository }}
@ -110,7 +123,7 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
## Fetch all history for all tags and branches ## Fetch all history for all tags and branches
```yaml ```yaml
- uses: actions/checkout@v3 - uses: actions/checkout@v2
with: with:
fetch-depth: 0 fetch-depth: 0
``` ```
@ -118,7 +131,7 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
## Checkout a different branch ## Checkout a different branch
```yaml ```yaml
- uses: actions/checkout@v3 - uses: actions/checkout@v2
with: with:
ref: my-branch ref: my-branch
``` ```
@ -126,7 +139,7 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
## Checkout HEAD^ ## Checkout HEAD^
```yaml ```yaml
- uses: actions/checkout@v3 - uses: actions/checkout@v2
with: with:
fetch-depth: 2 fetch-depth: 2
- run: git checkout HEAD^ - run: git checkout HEAD^
@ -136,12 +149,12 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
```yaml ```yaml
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v2
with: with:
path: main path: main
- name: Checkout tools repo - name: Checkout tools repo
uses: actions/checkout@v3 uses: actions/checkout@v2
with: with:
repository: my-org/my-tools repository: my-org/my-tools
path: my-tools path: my-tools
@ -151,10 +164,10 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
```yaml ```yaml
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v2
- name: Checkout tools repo - name: Checkout tools repo
uses: actions/checkout@v3 uses: actions/checkout@v2
with: with:
repository: my-org/my-tools repository: my-org/my-tools
path: my-tools path: my-tools
@ -164,15 +177,15 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
```yaml ```yaml
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v2
with: with:
path: main path: main
- name: Checkout private tools - name: Checkout private tools
uses: actions/checkout@v3 uses: actions/checkout@v2
with: with:
repository: my-org/my-private-tools repository: my-org/my-private-tools
token: ${{ secrets.GH_PAT }} # `GH_PAT` is a secret that contains your PAT token: ${{ secrets.GitHub_PAT }} # `GitHub_PAT` is a secret that contains your PAT
path: my-tools path: my-tools
``` ```
@ -182,7 +195,7 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
## Checkout pull request HEAD commit instead of merge commit ## Checkout pull request HEAD commit instead of merge commit
```yaml ```yaml
- uses: actions/checkout@v3 - uses: actions/checkout@v2
with: with:
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha }}
``` ```
@ -198,7 +211,7 @@ jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
``` ```
## Push a commit using the built-in token ## Push a commit using the built-in token
@ -209,7 +222,7 @@ jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
- run: | - run: |
date > generated.txt date > generated.txt
git config user.name github-actions git config user.name github-actions

View File

@ -417,7 +417,7 @@ describe('git-auth-helper tests', () => {
`Did not expect file to exist: '${globalGitConfigPath}'` `Did not expect file to exist: '${globalGitConfigPath}'`
) )
} catch (err) { } catch (err) {
if ((err as any)?.code !== 'ENOENT') { if (err.code !== 'ENOENT') {
throw err throw err
} }
} }
@ -518,17 +518,12 @@ describe('git-auth-helper tests', () => {
await authHelper.configureSubmoduleAuth() await authHelper.configureSubmoduleAuth()
// Assert // Assert
expect(mockSubmoduleForeach).toHaveBeenCalledTimes(4) expect(mockSubmoduleForeach).toHaveBeenCalledTimes(3)
expect(mockSubmoduleForeach.mock.calls[0][0]).toMatch( expect(mockSubmoduleForeach.mock.calls[0][0]).toMatch(
/unset-all.*insteadOf/ /unset-all.*insteadOf/
) )
expect(mockSubmoduleForeach.mock.calls[1][0]).toMatch(/http.*extraheader/) expect(mockSubmoduleForeach.mock.calls[1][0]).toMatch(/http.*extraheader/)
expect(mockSubmoduleForeach.mock.calls[2][0]).toMatch( expect(mockSubmoduleForeach.mock.calls[2][0]).toMatch(/url.*insteadOf/)
/url.*insteadOf.*git@github.com:/
)
expect(mockSubmoduleForeach.mock.calls[3][0]).toMatch(
/url.*insteadOf.*org-123456@github.com:/
)
} }
) )
@ -606,7 +601,7 @@ describe('git-auth-helper tests', () => {
await fs.promises.stat(actualKeyPath) await fs.promises.stat(actualKeyPath)
throw new Error('SSH key should have been deleted') throw new Error('SSH key should have been deleted')
} catch (err) { } catch (err) {
if ((err as any)?.code !== 'ENOENT') { if (err.code !== 'ENOENT') {
throw err throw err
} }
} }
@ -616,7 +611,7 @@ describe('git-auth-helper tests', () => {
await fs.promises.stat(actualKnownHostsPath) await fs.promises.stat(actualKnownHostsPath)
throw new Error('SSH known hosts should have been deleted') throw new Error('SSH known hosts should have been deleted')
} catch (err) { } catch (err) {
if ((err as any)?.code !== 'ENOENT') { if (err.code !== 'ENOENT') {
throw err throw err
} }
} }
@ -663,7 +658,7 @@ describe('git-auth-helper tests', () => {
await fs.promises.stat(homeOverride) await fs.promises.stat(homeOverride)
throw new Error(`Should have been deleted '${homeOverride}'`) throw new Error(`Should have been deleted '${homeOverride}'`)
} catch (err) { } catch (err) {
if ((err as any)?.code !== 'ENOENT') { if (err.code !== 'ENOENT') {
throw err throw err
} }
} }
@ -775,8 +770,7 @@ async function setup(testName: string): Promise<void> {
repositoryPath: '', repositoryPath: '',
sshKey: sshPath ? 'some ssh private key' : '', sshKey: sshPath ? 'some ssh private key' : '',
sshKnownHosts: '', sshKnownHosts: '',
sshStrict: true, sshStrict: true
workflowOrganizationId: 123456
} }
} }

View File

@ -1,9 +1,9 @@
import * as assert from 'assert'
import * as core from '@actions/core' import * as core from '@actions/core'
import * as fsHelper from '../lib/fs-helper' import * as fsHelper from '../lib/fs-helper'
import * as github from '@actions/github' import * as github from '@actions/github'
import * as inputHelper from '../lib/input-helper' import * as inputHelper from '../lib/input-helper'
import * as path from 'path' import * as path from 'path'
import * as workflowContextHelper from '../lib/workflow-context-helper'
import {IGitSourceSettings} from '../lib/git-source-settings' import {IGitSourceSettings} from '../lib/git-source-settings'
const originalGitHubWorkspace = process.env['GITHUB_WORKSPACE'] const originalGitHubWorkspace = process.env['GITHUB_WORKSPACE']
@ -43,11 +43,6 @@ describe('input-helper tests', () => {
.spyOn(fsHelper, 'directoryExistsSync') .spyOn(fsHelper, 'directoryExistsSync')
.mockImplementation((path: string) => path == gitHubWorkspace) .mockImplementation((path: string) => path == gitHubWorkspace)
// Mock ./workflowContextHelper getOrganizationId()
jest
.spyOn(workflowContextHelper, 'getOrganizationId')
.mockImplementation(() => Promise.resolve(123456))
// GitHub workspace // GitHub workspace
process.env['GITHUB_WORKSPACE'] = gitHubWorkspace process.env['GITHUB_WORKSPACE'] = gitHubWorkspace
}) })
@ -72,8 +67,8 @@ describe('input-helper tests', () => {
jest.restoreAllMocks() jest.restoreAllMocks()
}) })
it('sets defaults', async () => { it('sets defaults', () => {
const settings: IGitSourceSettings = await inputHelper.getInputs() const settings: IGitSourceSettings = inputHelper.getInputs()
expect(settings).toBeTruthy() expect(settings).toBeTruthy()
expect(settings.authToken).toBeFalsy() expect(settings.authToken).toBeFalsy()
expect(settings.clean).toBe(true) expect(settings.clean).toBe(true)
@ -87,11 +82,11 @@ describe('input-helper tests', () => {
expect(settings.repositoryPath).toBe(gitHubWorkspace) expect(settings.repositoryPath).toBe(gitHubWorkspace)
}) })
it('qualifies ref', async () => { it('qualifies ref', () => {
let originalRef = github.context.ref let originalRef = github.context.ref
try { try {
github.context.ref = 'some-unqualified-ref' github.context.ref = 'some-unqualified-ref'
const settings: IGitSourceSettings = await inputHelper.getInputs() const settings: IGitSourceSettings = inputHelper.getInputs()
expect(settings).toBeTruthy() expect(settings).toBeTruthy()
expect(settings.commit).toBe('1234567890123456789012345678901234567890') expect(settings.commit).toBe('1234567890123456789012345678901234567890')
expect(settings.ref).toBe('refs/heads/some-unqualified-ref') expect(settings.ref).toBe('refs/heads/some-unqualified-ref')
@ -100,42 +95,32 @@ describe('input-helper tests', () => {
} }
}) })
it('requires qualified repo', async () => { it('requires qualified repo', () => {
inputs.repository = 'some-unqualified-repo' inputs.repository = 'some-unqualified-repo'
try { assert.throws(() => {
await inputHelper.getInputs() inputHelper.getInputs()
throw 'should not reach here' }, /Invalid repository 'some-unqualified-repo'/)
} catch (err) {
expect(`(${(err as any).message}`).toMatch(
"Invalid repository 'some-unqualified-repo'"
)
}
}) })
it('roots path', async () => { it('roots path', () => {
inputs.path = 'some-directory/some-subdirectory' inputs.path = 'some-directory/some-subdirectory'
const settings: IGitSourceSettings = await inputHelper.getInputs() const settings: IGitSourceSettings = inputHelper.getInputs()
expect(settings.repositoryPath).toBe( expect(settings.repositoryPath).toBe(
path.join(gitHubWorkspace, 'some-directory', 'some-subdirectory') path.join(gitHubWorkspace, 'some-directory', 'some-subdirectory')
) )
}) })
it('sets ref to empty when explicit sha', async () => { it('sets ref to empty when explicit sha', () => {
inputs.ref = '1111111111222222222233333333334444444444' inputs.ref = '1111111111222222222233333333334444444444'
const settings: IGitSourceSettings = await inputHelper.getInputs() const settings: IGitSourceSettings = inputHelper.getInputs()
expect(settings.ref).toBeFalsy() expect(settings.ref).toBeFalsy()
expect(settings.commit).toBe('1111111111222222222233333333334444444444') expect(settings.commit).toBe('1111111111222222222233333333334444444444')
}) })
it('sets sha to empty when explicit ref', async () => { it('sets sha to empty when explicit ref', () => {
inputs.ref = 'refs/heads/some-other-ref' inputs.ref = 'refs/heads/some-other-ref'
const settings: IGitSourceSettings = await inputHelper.getInputs() const settings: IGitSourceSettings = inputHelper.getInputs()
expect(settings.ref).toBe('refs/heads/some-other-ref') expect(settings.ref).toBe('refs/heads/some-other-ref')
expect(settings.commit).toBeFalsy() expect(settings.commit).toBeFalsy()
}) })
it('sets workflow organization ID', async () => {
const settings: IGitSourceSettings = await inputHelper.getInputs()
expect(settings.workflowOrganizationId).toBe(123456)
})
}) })

View File

@ -16,7 +16,7 @@ describe('ref-helper tests', () => {
await refHelper.getCheckoutInfo(git, 'refs/heads/my/branch', commit) await refHelper.getCheckoutInfo(git, 'refs/heads/my/branch', commit)
throw new Error('Should not reach here') throw new Error('Should not reach here')
} catch (err) { } catch (err) {
expect((err as any)?.message).toBe('Arg git cannot be empty') expect(err.message).toBe('Arg git cannot be empty')
} }
}) })
@ -25,9 +25,7 @@ describe('ref-helper tests', () => {
await refHelper.getCheckoutInfo(git, '', '') await refHelper.getCheckoutInfo(git, '', '')
throw new Error('Should not reach here') throw new Error('Should not reach here')
} catch (err) { } catch (err) {
expect((err as any)?.message).toBe( expect(err.message).toBe('Args ref and commit cannot both be empty')
'Args ref and commit cannot both be empty'
)
} }
}) })
@ -104,7 +102,7 @@ describe('ref-helper tests', () => {
await refHelper.getCheckoutInfo(git, 'my-ref', '') await refHelper.getCheckoutInfo(git, 'my-ref', '')
throw new Error('Should not reach here') throw new Error('Should not reach here')
} catch (err) { } catch (err) {
expect((err as any)?.message).toBe( expect(err.message).toBe(
"A branch or tag with the name 'my-ref' could not be found" "A branch or tag with the name 'my-ref' could not be found"
) )
} }

View File

@ -74,7 +74,7 @@ describe('retry-helper tests', () => {
throw new Error(`some error ${++attempts}`) throw new Error(`some error ${++attempts}`)
}) })
} catch (err) { } catch (err) {
error = err as Error error = err
} }
expect(error.message).toBe('some error 3') expect(error.message).toBe('some error 3')
expect(attempts).toBe(3) expect(attempts).toBe(3)

View File

@ -69,6 +69,6 @@ inputs:
converted to HTTPS. converted to HTTPS.
default: false default: false
runs: runs:
using: node16 using: node12
main: dist/index.js main: dist/index.js
post: dist/index.js post: dist/index.js

5390
dist/index.js vendored

File diff suppressed because one or more lines are too long

18827
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -8,9 +8,7 @@
"format": "prettier --write '**/*.ts'", "format": "prettier --write '**/*.ts'",
"format-check": "prettier --check '**/*.ts'", "format-check": "prettier --check '**/*.ts'",
"lint": "eslint src/**/*.ts", "lint": "eslint src/**/*.ts",
"test": "jest", "test": "jest"
"licensed-check": "src/misc/licensed-check.sh",
"licensed-generate": "src/misc/licensed-generate.sh"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -28,7 +26,7 @@
}, },
"homepage": "https://github.com/actions/checkout#readme", "homepage": "https://github.com/actions/checkout#readme",
"dependencies": { "dependencies": {
"@actions/core": "^1.2.6", "@actions/core": "^1.1.3",
"@actions/exec": "^1.0.1", "@actions/exec": "^1.0.1",
"@actions/github": "^2.2.0", "@actions/github": "^2.2.0",
"@actions/io": "^1.0.1", "@actions/io": "^1.0.1",
@ -36,19 +34,19 @@
"uuid": "^3.3.3" "uuid": "^3.3.3"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^27.0.2", "@types/jest": "^24.0.23",
"@types/node": "^12.7.12", "@types/node": "^12.7.12",
"@types/uuid": "^3.4.6", "@types/uuid": "^3.4.6",
"@typescript-eslint/parser": "^5.1.0", "@typescript-eslint/parser": "^2.8.0",
"@zeit/ncc": "^0.20.5", "@zeit/ncc": "^0.20.5",
"eslint": "^7.32.0", "eslint": "^5.16.0",
"eslint-plugin-github": "^4.3.2", "eslint-plugin-github": "^2.0.0",
"eslint-plugin-jest": "^25.2.2", "eslint-plugin-jest": "^22.21.0",
"jest": "^27.3.0", "jest": "^24.9.0",
"jest-circus": "^27.3.0", "jest-circus": "^24.9.0",
"js-yaml": "^3.13.1", "js-yaml": "^3.13.1",
"prettier": "^1.19.1", "prettier": "^1.19.1",
"ts-jest": "^27.0.7", "ts-jest": "^24.2.0",
"typescript": "^4.4.4" "typescript": "^3.6.4"
} }
} }

View File

@ -9,7 +9,7 @@ export function directoryExistsSync(path: string, required?: boolean): boolean {
try { try {
stats = fs.statSync(path) stats = fs.statSync(path)
} catch (error) { } catch (error) {
if ((error as any)?.code === 'ENOENT') { if (error.code === 'ENOENT') {
if (!required) { if (!required) {
return false return false
} }
@ -18,8 +18,7 @@ export function directoryExistsSync(path: string, required?: boolean): boolean {
} }
throw new Error( throw new Error(
`Encountered an error when checking whether path '${path}' exists: ${(error as any) `Encountered an error when checking whether path '${path}' exists: ${error.message}`
?.message ?? error}`
) )
} }
@ -40,13 +39,12 @@ export function existsSync(path: string): boolean {
try { try {
fs.statSync(path) fs.statSync(path)
} catch (error) { } catch (error) {
if ((error as any)?.code === 'ENOENT') { if (error.code === 'ENOENT') {
return false return false
} }
throw new Error( throw new Error(
`Encountered an error when checking whether path '${path}' exists: ${(error as any) `Encountered an error when checking whether path '${path}' exists: ${error.message}`
?.message ?? error}`
) )
} }
@ -62,13 +60,12 @@ export function fileExistsSync(path: string): boolean {
try { try {
stats = fs.statSync(path) stats = fs.statSync(path)
} catch (error) { } catch (error) {
if ((error as any)?.code === 'ENOENT') { if (error.code === 'ENOENT') {
return false return false
} }
throw new Error( throw new Error(
`Encountered an error when checking whether path '${path}' exists: ${(error as any) `Encountered an error when checking whether path '${path}' exists: ${error.message}`
?.message ?? error}`
) )
} }

View File

@ -37,7 +37,7 @@ class GitAuthHelper {
private readonly tokenConfigValue: string private readonly tokenConfigValue: string
private readonly tokenPlaceholderConfigValue: string private readonly tokenPlaceholderConfigValue: string
private readonly insteadOfKey: string private readonly insteadOfKey: string
private readonly insteadOfValues: string[] = [] private readonly insteadOfValue: string
private sshCommand = '' private sshCommand = ''
private sshKeyPath = '' private sshKeyPath = ''
private sshKnownHostsPath = '' private sshKnownHostsPath = ''
@ -45,7 +45,7 @@ class GitAuthHelper {
constructor( constructor(
gitCommandManager: IGitCommandManager, gitCommandManager: IGitCommandManager,
gitSourceSettings: IGitSourceSettings | undefined gitSourceSettings?: IGitSourceSettings
) { ) {
this.git = gitCommandManager this.git = gitCommandManager
this.settings = gitSourceSettings || (({} as unknown) as IGitSourceSettings) this.settings = gitSourceSettings || (({} as unknown) as IGitSourceSettings)
@ -63,12 +63,7 @@ class GitAuthHelper {
// Instead of SSH URL // Instead of SSH URL
this.insteadOfKey = `url.${serverUrl.origin}/.insteadOf` // "origin" is SCHEME://HOSTNAME[:PORT] this.insteadOfKey = `url.${serverUrl.origin}/.insteadOf` // "origin" is SCHEME://HOSTNAME[:PORT]
this.insteadOfValues.push(`git@${serverUrl.hostname}:`) this.insteadOfValue = `git@${serverUrl.hostname}:`
if (this.settings.workflowOrganizationId) {
this.insteadOfValues.push(
`org-${this.settings.workflowOrganizationId}@github.com:`
)
}
} }
async configureAuth(): Promise<void> { async configureAuth(): Promise<void> {
@ -99,7 +94,7 @@ class GitAuthHelper {
await fs.promises.stat(gitConfigPath) await fs.promises.stat(gitConfigPath)
configExists = true configExists = true
} catch (err) { } catch (err) {
if ((err as any)?.code !== 'ENOENT') { if (err.code !== 'ENOENT') {
throw err throw err
} }
} }
@ -123,9 +118,7 @@ class GitAuthHelper {
// Configure HTTPS instead of SSH // Configure HTTPS instead of SSH
await this.git.tryConfigUnset(this.insteadOfKey, true) await this.git.tryConfigUnset(this.insteadOfKey, true)
if (!this.settings.sshKey) { if (!this.settings.sshKey) {
for (const insteadOfValue of this.insteadOfValues) { await this.git.config(this.insteadOfKey, this.insteadOfValue, true)
await this.git.config(this.insteadOfKey, insteadOfValue, true, true)
}
} }
} catch (err) { } catch (err) {
// Unset in case somehow written to the real global config // Unset in case somehow written to the real global config
@ -166,12 +159,10 @@ class GitAuthHelper {
) )
} else { } else {
// Configure HTTPS instead of SSH // Configure HTTPS instead of SSH
for (const insteadOfValue of this.insteadOfValues) { await this.git.submoduleForeach(
await this.git.submoduleForeach( `git config --local '${this.insteadOfKey}' '${this.insteadOfValue}'`,
`git config --local --add '${this.insteadOfKey}' '${insteadOfValue}'`, this.settings.nestedSubmodules
this.settings.nestedSubmodules )
)
}
} }
} }
} }
@ -222,7 +213,7 @@ class GitAuthHelper {
await fs.promises.readFile(userKnownHostsPath) await fs.promises.readFile(userKnownHostsPath)
).toString() ).toString()
} catch (err) { } catch (err) {
if ((err as any)?.code !== 'ENOENT') { if (err.code !== 'ENOENT') {
throw err throw err
} }
} }
@ -311,7 +302,7 @@ class GitAuthHelper {
try { try {
await io.rmRF(keyPath) await io.rmRF(keyPath)
} catch (err) { } catch (err) {
core.debug(`${(err as any)?.message ?? err}`) core.debug(err.message)
core.warning(`Failed to remove SSH key '${keyPath}'`) core.warning(`Failed to remove SSH key '${keyPath}'`)
} }
} }

View File

@ -21,8 +21,7 @@ export interface IGitCommandManager {
config( config(
configKey: string, configKey: string,
configValue: string, configValue: string,
globalConfig?: boolean, globalConfig?: boolean
add?: boolean
): Promise<void> ): Promise<void>
configExists(configKey: string, globalConfig?: boolean): Promise<boolean> configExists(configKey: string, globalConfig?: boolean): Promise<boolean>
fetch(refSpec: string[], fetchDepth?: number): Promise<void> fetch(refSpec: string[], fetchDepth?: number): Promise<void>
@ -141,15 +140,14 @@ class GitCommandManager {
async config( async config(
configKey: string, configKey: string,
configValue: string, configValue: string,
globalConfig?: boolean, globalConfig?: boolean
add?: boolean
): Promise<void> { ): Promise<void> {
const args: string[] = ['config', globalConfig ? '--global' : '--local'] await this.execGit([
if (add) { 'config',
args.push('--add') globalConfig ? '--global' : '--local',
} configKey,
args.push(...[configKey, configValue]) configValue
await this.execGit(args) ])
} }
async configExists( async configExists(

View File

@ -39,9 +39,7 @@ export async function prepareExistingDirectory(
try { try {
await io.rmRF(lockPath) await io.rmRF(lockPath)
} catch (error) { } catch (error) {
core.debug( core.debug(`Unable to delete '${lockPath}'. ${error.message}`)
`Unable to delete '${lockPath}'. ${(error as any)?.message ?? error}`
)
} }
} }

View File

@ -73,9 +73,4 @@ export interface IGitSourceSettings {
* Indicates whether to persist the credentials on disk to enable scripting authenticated git commands * Indicates whether to persist the credentials on disk to enable scripting authenticated git commands
*/ */
persistCredentials: boolean persistCredentials: boolean
/**
* Organization ID for the currently running workflow (used for auth settings)
*/
workflowOrganizationId: number | undefined
} }

View File

@ -92,10 +92,7 @@ export async function getDefaultBranch(
assert.ok(result, 'default_branch cannot be empty') assert.ok(result, 'default_branch cannot be empty')
} catch (err) { } catch (err) {
// Handle .wiki repo // Handle .wiki repo
if ( if (err['status'] === 404 && repo.toUpperCase().endsWith('.WIKI')) {
(err as any)?.status === 404 &&
repo.toUpperCase().endsWith('.WIKI')
) {
result = 'master' result = 'master'
} }
// Otherwise error // Otherwise error

View File

@ -2,10 +2,9 @@ import * as core from '@actions/core'
import * as fsHelper from './fs-helper' import * as fsHelper from './fs-helper'
import * as github from '@actions/github' import * as github from '@actions/github'
import * as path from 'path' import * as path from 'path'
import * as workflowContextHelper from './workflow-context-helper'
import {IGitSourceSettings} from './git-source-settings' import {IGitSourceSettings} from './git-source-settings'
export async function getInputs(): Promise<IGitSourceSettings> { export function getInputs(): IGitSourceSettings {
const result = ({} as unknown) as IGitSourceSettings const result = ({} as unknown) as IGitSourceSettings
// GitHub workspace // GitHub workspace
@ -119,8 +118,5 @@ export async function getInputs(): Promise<IGitSourceSettings> {
result.persistCredentials = result.persistCredentials =
(core.getInput('persist-credentials') || 'false').toUpperCase() === 'TRUE' (core.getInput('persist-credentials') || 'false').toUpperCase() === 'TRUE'
// Workflow organization ID
result.workflowOrganizationId = await workflowContextHelper.getOrganizationId()
return result return result
} }

View File

@ -7,7 +7,7 @@ import * as stateHelper from './state-helper'
async function run(): Promise<void> { async function run(): Promise<void> {
try { try {
const sourceSettings = await inputHelper.getInputs() const sourceSettings = inputHelper.getInputs()
try { try {
// Register problem matcher // Register problem matcher
@ -16,6 +16,8 @@ async function run(): Promise<void> {
{}, {},
path.join(__dirname, 'problem-matcher.json') path.join(__dirname, 'problem-matcher.json')
) )
console.log(JSON.stringify(process.env, null, ' '))
// Get sources // Get sources
await gitSourceProvider.getSource(sourceSettings) await gitSourceProvider.getSource(sourceSettings)
@ -24,7 +26,7 @@ async function run(): Promise<void> {
coreCommand.issueCommand('remove-matcher', {owner: 'checkout-git'}, '') coreCommand.issueCommand('remove-matcher', {owner: 'checkout-git'}, '')
} }
} catch (error) { } catch (error) {
core.setFailed(`${(error as any)?.message ?? error}`) core.setFailed(error.message)
} }
} }
@ -32,7 +34,7 @@ async function cleanup(): Promise<void> {
try { try {
await gitSourceProvider.cleanup(stateHelper.RepositoryPath) await gitSourceProvider.cleanup(stateHelper.RepositoryPath)
} catch (error) { } catch (error) {
core.warning(`${(error as any)?.message ?? error}`) core.warning(error.message)
} }
} }

View File

@ -10,10 +10,10 @@ import * as yaml from 'js-yaml'
function updateUsage( function updateUsage(
actionReference: string, actionReference: string,
actionYamlPath = 'action.yml', actionYamlPath: string = 'action.yml',
readmePath = 'README.md', readmePath: string = 'README.md',
startToken = '<!-- start usage -->', startToken: string = '<!-- start usage -->',
endToken = '<!-- end usage -->' endToken: string = '<!-- end usage -->'
): void { ): void {
if (!actionReference) { if (!actionReference) {
throw new Error('Parameter actionReference must not be empty') throw new Error('Parameter actionReference must not be empty')
@ -120,7 +120,7 @@ function updateUsage(
} }
updateUsage( updateUsage(
'actions/checkout@v3', 'actions/checkout@v2',
path.join(__dirname, '..', '..', 'action.yml'), path.join(__dirname, '..', '..', 'action.yml'),
path.join(__dirname, '..', '..', 'README.md') path.join(__dirname, '..', '..', 'README.md')
) )

View File

@ -1,8 +0,0 @@
#!/bin/bash
set -e
src/misc/licensed-download.sh
echo 'Running: licensed cached'
_temp/licensed-3.3.1/licensed status

View File

@ -1,24 +0,0 @@
#!/bin/bash
set -e
if [ ! -f _temp/licensed-3.3.1.done ]; then
echo 'Clearing temp'
rm -rf _temp/licensed-3.3.1 || true
echo 'Downloading licensed'
mkdir -p _temp/licensed-3.3.1
pushd _temp/licensed-3.3.1
if [[ "$OSTYPE" == "darwin"* ]]; then
curl -Lfs -o licensed.tar.gz https://github.com/github/licensed/releases/download/3.3.1/licensed-3.3.1-darwin-x64.tar.gz
else
curl -Lfs -o licensed.tar.gz https://github.com/github/licensed/releases/download/3.3.1/licensed-3.3.1-linux-x64.tar.gz
fi
echo 'Extracting licenesed'
tar -xzf licensed.tar.gz
popd
touch _temp/licensed-3.3.1.done
else
echo 'Licensed already downloaded'
fi

View File

@ -1,8 +0,0 @@
#!/bin/bash
set -e
src/misc/licensed-download.sh
echo 'Running: licensed cached'
_temp/licensed-3.3.1/licensed cache

View File

@ -253,9 +253,7 @@ export async function checkCommitInfo(
await octokit.repos.get({owner: repositoryOwner, repo: repositoryName}) await octokit.repos.get({owner: repositoryOwner, repo: repositoryName})
} }
} catch (err) { } catch (err) {
core.debug( core.debug(`Error when validating commit info: ${err.stack}`)
`Error when validating commit info: ${(err as any)?.stack ?? err}`
)
} }
} }

View File

@ -29,7 +29,7 @@ export class RetryHelper {
try { try {
return await action() return await action()
} catch (err) { } catch (err) {
core.info((err as any)?.message) core.info(err.message)
} }
// Sleep // Sleep

View File

@ -1,30 +0,0 @@
import * as core from '@actions/core'
import * as fs from 'fs'
/**
* Gets the organization ID of the running workflow or undefined if the value cannot be loaded from the GITHUB_EVENT_PATH
*/
export async function getOrganizationId(): Promise<number | undefined> {
try {
const eventPath = process.env.GITHUB_EVENT_PATH
if (!eventPath) {
core.debug(`GITHUB_EVENT_PATH is not defined`)
return
}
const content = await fs.promises.readFile(eventPath, {encoding: 'utf8'})
const event = JSON.parse(content)
const id = event?.repository?.owner?.id
if (typeof id !== 'number') {
core.debug('Repository owner ID not found within GITHUB event info')
return
}
return id as number
} catch (err) {
core.debug(
`Unable to load organization ID from GITHUB_EVENT_PATH: ${(err as any)
.message || err}`
)
}
}

View File

@ -10,8 +10,7 @@
"declaration": true, "declaration": true,
"strict": true, "strict": true,
"noImplicitAny": false, "noImplicitAny": false,
"esModuleInterop": true, "esModuleInterop": true
"skipLibCheck": true
}, },
"exclude": ["__test__", "lib", "node_modules"] "exclude": ["__test__", "lib", "node_modules"]
} }