1
0
mirror of https://github.com/actions/checkout.git synced 2026-06-22 03:41:20 +08:00

Compare commits

...

37 Commits

Author SHA1 Message Date
Tingluo Huang ee0669bd1c Add new public key for known_hosts (#1237) (#1238)
* Add new public key for known_hosts (#1237)

* Add new public key for known_hosts

* Fix the build!

* fix build.

---------

Co-authored-by: Cameron Booth <cdb@github.com>
2023-03-24 02:04:47 -04:00
Cory Miller dc323e67f1 Add backports to v2 branch (#1040)
* Update licensed version
* Backport for submodule command wrapping
* Update NPM packages
* Update dist/index.js
* Rebuild using Node 12
* Rebuild after a more aggressive cleanup of local files
* Backport change to replace datadog/squid with ubuntu/squid
2022-12-13 10:14:06 -05:00
Francesco Renzi e2f20e631a Update CHANGELOG.md 2022-10-13 16:50:56 +01:00
Francesco Renzi b2eb13baee Update @actions/core to 1.10.0 (#962)
* Update @actions/core to 1.10.0

* Backport state-helper updates
2022-10-13 16:49:13 +01:00
Tingluo Huang 7884fcad6b Prepare changelog for v2.4.2. (#778) 2022-04-21 10:45:29 -04:00
Tingluo Huang f67ee5d622 Add set-safe-directory input to allow customers to take control. (#770) (#776)
* Add set-safe-directory input to allow customers to take control.
2022-04-21 10:12:11 -04:00
Thomas Boop f25a3a9f25 Safe Directory v2 update (#764)
* set safe directory when running checkout
2022-04-14 12:12:00 -04:00
Ameya Lokare 230611dbd0 Change secret name for PAT to not start with GITHUB_ (#623)
Github doesn't allow secret names that start with `GITHUB_` (case insensitive). Update README to choose a different prefix (GH).
2021-11-02 16:20:59 -05:00
eric sciple ec3a7ce113 set insteadOf url for org-id (#621) 2021-11-01 11:43:18 -05:00
eric sciple fd47087372 codeql should analyze lib not dist (#620) 2021-10-20 15:11:24 -05:00
eric sciple 3d677ac575 script to generate license info (#614) 2021-10-19 14:30:04 -05:00
eric sciple 826ba42d6c npm audit fix (#612) 2021-10-19 10:05:28 -05:00
eric sciple eb8a193c1d update dev dependencies and react to new linting rules (#611) 2021-10-19 09:52:57 -05:00
Jeremy Epling c49af7ca1f Create codeql-analysis.yml (#602) 2021-10-18 16:28:25 -05:00
Thomas Boop 1e204e9a92 update licensed check (#606) 2021-10-13 16:22:03 -05:00
eric sciple 0299a0d2b6 update dist (#605) 2021-10-13 16:07:05 -05:00
dependabot[bot] be0f448456 Bump ws from 5.2.2 to 5.2.3 (#604)
Bumps [ws](https://github.com/websockets/ws) from 5.2.2 to 5.2.3.
- [Release notes](https://github.com/websockets/ws/releases)
- [Commits](https://github.com/websockets/ws/compare/5.2.2...5.2.3)

---
updated-dependencies:
- dependency-name: ws
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-13 09:14:20 -05:00
dependabot[bot] 56c00a7b1f Bump tmpl from 1.0.4 to 1.0.5 (#588)
Bumps [tmpl](https://github.com/daaku/nodejs-tmpl) from 1.0.4 to 1.0.5.
- [Release notes](https://github.com/daaku/nodejs-tmpl/releases)
- [Commits](https://github.com/daaku/nodejs-tmpl/commits/v1.0.5)

---
updated-dependencies:
- dependency-name: tmpl
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-13 09:13:31 -05:00
dependabot[bot] 85e47d1a2b Bump path-parse from 1.0.6 to 1.0.7 (#568)
Bumps [path-parse](https://github.com/jbgutierrez/path-parse) from 1.0.6 to 1.0.7.
- [Release notes](https://github.com/jbgutierrez/path-parse/releases)
- [Commits](https://github.com/jbgutierrez/path-parse/commits/v1.0.7)

---
updated-dependencies:
- dependency-name: path-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-13 09:13:04 -05:00
dependabot[bot] 3fc17f8645 Bump hosted-git-info from 2.8.5 to 2.8.9 (#500)
Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.5 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.5...v2.8.9)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-13 09:11:06 -05:00
dependabot[bot] e3bc06d986 Bump lodash from 4.17.15 to 4.17.21 (#499)
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.21.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.21)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-13 09:08:31 -05:00
dependabot[bot] 442567ba57 Bump handlebars from 4.5.3 to 4.7.7 (#497)
Bumps [handlebars](https://github.com/wycats/handlebars.js) from 4.5.3 to 4.7.7.
- [Release notes](https://github.com/wycats/handlebars.js/releases)
- [Changelog](https://github.com/handlebars-lang/handlebars.js/blob/master/release-notes.md)
- [Commits](https://github.com/wycats/handlebars.js/compare/v4.5.3...v4.7.7)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-13 09:07:45 -05:00
dependabot[bot] 7f00b66d06 Bump y18n from 4.0.0 to 4.0.1 (#469)
Bumps [y18n](https://github.com/yargs/y18n) from 4.0.0 to 4.0.1.
- [Release notes](https://github.com/yargs/y18n/releases)
- [Changelog](https://github.com/yargs/y18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/yargs/y18n/commits)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-13 09:07:05 -05:00
dependabot[bot] eccf386318 Bump @actions/core from 1.1.3 to 1.2.6 (#361)
Bumps [@actions/core](https://github.com/actions/toolkit/tree/HEAD/packages/core) from 1.1.3 to 1.2.6.
- [Release notes](https://github.com/actions/toolkit/releases)
- [Changelog](https://github.com/actions/toolkit/blob/main/packages/core/RELEASES.md)
- [Commits](https://github.com/actions/toolkit/commits/HEAD/packages/core)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-13 08:57:33 -05:00
dependabot[bot] 2bd2911be9 Bump acorn from 5.7.3 to 5.7.4 (#186)
Bumps [acorn](https://github.com/acornjs/acorn) from 5.7.3 to 5.7.4.
- [Release notes](https://github.com/acornjs/acorn/releases)
- [Commits](https://github.com/acornjs/acorn/compare/5.7.3...5.7.4)

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-13 08:55:25 -05:00
Brian Cristante afe4af09a7 Create check-dist.yml (#566)
* Add check-dist.yml

* Don't need to mv to git diff

* Upload the whole dist/ directory as an artifact

* Update .github/workflows/check-dist.yml
2021-08-17 16:08:22 -04:00
Ross Brodbeck 25a956c84d Create CODEOWNERS 2021-02-04 12:25:41 -05:00
Johannes Schindelin 5a4ac9002d Add missing awaits (#379)
* auth-helper: properly await replacement of the token value in the config

After writing the `.extraheader` config, we manually replace the token
with the actual value. This is done in an `async` function, but we were
not `await`ing the result.

In our tests, this commit fixes a flakiness we observed where
`remote.origin.url` sometimes (very rarely, actually) is not set for
submodules. Our interpretation is that the configs are in the process of
being rewritten with the correct token value _while_ another `git
config` that wants to set the `insteadOf` value is reading the config,
which is currently empty.

A more idiomatic way to fix this in Typescript would use
`Promise.all()`, like this:

      await Promise.all(
        configPaths.map(async configPath => {
          core.debug(`Replacing token placeholder in '${configPath}'`)
          await this.replaceTokenPlaceholder(configPath)
        })
      )

However, during review of https://github.com/actions/checkout/pull/379
it was decided to keep the `for` loop in the interest of simplicity.

Reported by Ian Lynagh.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>

* downloadRepository(): await the result of recursive deletions

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>

* Ask ESLint to report floating Promises

This rule is quite helpful in avoiding hard-to-debug missing `await`s.

Note: there are two locations in `src/main.ts` that trigger warnings:
the `run()` and the `cleanup()` function are called without `await` and
without any `.catch()` clause.

In the initial version of https://github.com/actions/checkout/pull/379,
this was addressed by adding `.catch()` clauses. However, it was
determined that this is boilerplate code that will need to be fixed in a
broader way.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>

* Rebuild

This trick was brought to you by `npm ci && npm run build`. Needed to
get the PR build to pass.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2020-11-03 09:44:09 -05:00
Thomas Boop c952173edf Swap to Environment Files (#360) 2020-09-30 11:41:09 -04:00
Thomas Boop a81bbbf829 Remove unneeded commit information from build logs (#345)
* Remove unneeded commit information from stdout
2020-09-23 09:41:47 -04:00
Thomas Boop 21dc310f19 Add Licensed To Help Verify Prod Licenses (#326)
* Add Licensed file and workflow

* manual updates of dependencies

* Delete licenses.txt

* Ignore Generated Files in Git PR's
2020-09-10 09:24:29 -04:00
Thomas Boop be6c44d969 Revert "Delete licenses.txt" 2020-08-11 19:41:01 -04:00
Thomas Boop dac8cc78a1 Delete licenses.txt 2020-08-11 19:36:35 -04:00
Thomas Boop 2036a08e25 Add Third Party License Information to Dist Files (#320) 2020-08-07 09:22:39 -04:00
eric sciple 592cf69a22 Update README.md 2020-07-14 16:30:57 -04:00
eric sciple a4b69b4886 Update README.md 2020-07-14 13:08:52 -04:00
eric sciple 1433f62caa update default branch (#305) 2020-07-14 09:23:30 -04:00
112 changed files with 20138 additions and 5711 deletions
+2 -7
View File
@@ -1,6 +1,6 @@
{ {
"plugins": ["jest", "@typescript-eslint"], "plugins": ["jest", "@typescript-eslint"],
"extends": ["plugin:github/es6"], "extends": ["plugin:github/recommended"],
"parser": "@typescript-eslint/parser", "parser": "@typescript-eslint/parser",
"parserOptions": { "parserOptions": {
"ecmaVersion": 9, "ecmaVersion": 9,
@@ -16,23 +16,19 @@
"@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",
"@typescript-eslint/no-extraneous-class": "error", "@typescript-eslint/no-extraneous-class": "error",
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-for-in-array": "error", "@typescript-eslint/no-for-in-array": "error",
"@typescript-eslint/no-inferrable-types": "error", "@typescript-eslint/no-inferrable-types": "error",
"@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",
@@ -40,7 +36,6 @@
"@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",
+1
View File
@@ -0,0 +1 @@
.licenses/** -diff linguist-generated=true
+51
View File
@@ -0,0 +1,51 @@
# `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 12.x
uses: actions/setup-node@v1
with:
node-version: 12.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/
+58
View File
@@ -0,0 +1,58 @@
# 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
+14
View File
@@ -0,0 +1,14 @@
name: Licensed
on:
push: {branches: main}
pull_request: {branches: main}
jobs:
test:
runs-on: ubuntu-latest
name: Check licenses
steps:
- uses: actions/checkout@v2
- run: npm ci
- run: npm run licensed-check
+40 -2
View File
@@ -4,7 +4,7 @@ on:
pull_request: pull_request:
push: push:
branches: branches:
- master - main
- releases/* - releases/*
jobs: jobs:
@@ -142,7 +142,7 @@ jobs:
options: --dns 127.0.0.1 options: --dns 127.0.0.1
services: services:
squid-proxy: squid-proxy:
image: datadog/squid:latest image: ubuntu/squid:latest
ports: ports:
- 3128:3128 - 3128:3128
env: env:
@@ -205,3 +205,41 @@ jobs:
path: basic path: basic
- name: Verify basic - name: Verify basic
run: __test__/verify-basic.sh --archive run: __test__/verify-basic.sh --archive
test-git-container:
runs-on: ubuntu-latest
container: bitnami/git:latest
steps:
# Clone this repo
- name: Checkout
uses: actions/checkout@v3
with:
path: v3
# Basic checkout using git
- name: Checkout basic
uses: ./v3
with:
ref: test-data/v2/basic
- name: Verify basic
run: |
if [ ! -f "./basic-file.txt" ]; then
echo "Expected basic file does not exist"
exit 1
fi
# Verify .git folder
if [ ! -d "./.git" ]; then
echo "Expected ./.git folder to exist"
exit 1
fi
# Verify auth token
git config --global --add safe.directory "*"
git fetch --no-tags --depth=1 origin +refs/heads/main:refs/remotes/origin/main
# needed to make checkout post cleanup succeed
- name: Fix Checkout v3
uses: actions/checkout@v3
with:
path: v3
+1
View File
@@ -1,3 +1,4 @@
__test__/_temp __test__/_temp
_temp/
lib/ lib/
node_modules/ node_modules/
+14
View File
@@ -0,0 +1,14 @@
sources:
npm: true
allowed:
- apache-2.0
- bsd-2-clause
- bsd-3-clause
- isc
- mit
- cc0-1.0
- unlicense
reviewed:
npm:
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.
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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
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
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
+9
View File
@@ -1,5 +1,14 @@
# Changelog # Changelog
## v2.5.0
- [Bump @actions/core to v1.10.0](https://github.com/actions/checkout/pull/962)
## v2.4.2
- [Add input `set-safe-directory`](https://github.com/actions/checkout/pull/776)
## v2.4.1
- [Set the safe directory option on git to prevent git commands failing when running in containers](https://github.com/actions/checkout/pull/762)
## v2.3.1 ## v2.3.1
- [Fix default branch resolution for .wiki and when using SSH](https://github.com/actions/checkout/pull/284) - [Fix default branch resolution for .wiki and when using SSH](https://github.com/actions/checkout/pull/284)
+1
View File
@@ -0,0 +1 @@
* @actions/actions-runtime
+26 -2
View File
@@ -105,6 +105,11 @@ Refer [here](https://github.com/actions/checkout/blob/v1/README.md) for previous
# #
# Default: false # Default: false
submodules: '' submodules: ''
# Add repository path as safe.directory for Git global config by running `git
# config --global --add safe.directory <path>`
# Default: true
set-safe-directory: ''
``` ```
<!-- end usage --> <!-- end usage -->
@@ -118,6 +123,7 @@ Refer [here](https://github.com/actions/checkout/blob/v1/README.md) for previous
- [Checkout multiple repos (private)](#Checkout-multiple-repos-private) - [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 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 pull request on closed event](#Checkout-pull-request-on-closed-event)
- [Push a commit using the built-in token](#Push-a-commit-using-the-built-in-token)
## Fetch all history for all tags and branches ## Fetch all history for all tags and branches
@@ -184,7 +190,7 @@ Refer [here](https://github.com/actions/checkout/blob/v1/README.md) for previous
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
repository: my-org/my-private-tools repository: my-org/my-private-tools
token: ${{ secrets.GitHub_PAT }} # `GitHub_PAT` is a secret that contains your PAT token: ${{ secrets.GH_PAT }} # `GH_PAT` is a secret that contains your PAT
path: my-tools path: my-tools
``` ```
@@ -204,7 +210,7 @@ Refer [here](https://github.com/actions/checkout/blob/v1/README.md) for previous
```yaml ```yaml
on: on:
pull_request: pull_request:
branches: [master] branches: [main]
types: [opened, synchronize, closed] types: [opened, synchronize, closed]
jobs: jobs:
build: build:
@@ -213,6 +219,24 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
``` ```
## Push a commit using the built-in token
```yaml
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: |
date > generated.txt
git config user.name github-actions
git config user.email github-actions@github.com
git add .
git commit -m "generated"
git push
```
# License # License
The scripts and documentation in this project are released under the [MIT License](LICENSE) The scripts and documentation in this project are released under the [MIT License](LICENSE)
+20 -12
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.code !== 'ENOENT') { if ((err as any)?.code !== 'ENOENT') {
throw err throw err
} }
} }
@@ -518,12 +518,17 @@ describe('git-auth-helper tests', () => {
await authHelper.configureSubmoduleAuth() await authHelper.configureSubmoduleAuth()
// Assert // Assert
expect(mockSubmoduleForeach).toHaveBeenCalledTimes(3) expect(mockSubmoduleForeach).toHaveBeenCalledTimes(4)
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(/url.*insteadOf/) expect(mockSubmoduleForeach.mock.calls[2][0]).toMatch(
/url.*insteadOf.*git@github.com:/
)
expect(mockSubmoduleForeach.mock.calls[3][0]).toMatch(
/url.*insteadOf.*org-123456@github.com:/
)
} }
) )
@@ -601,7 +606,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.code !== 'ENOENT') { if ((err as any)?.code !== 'ENOENT') {
throw err throw err
} }
} }
@@ -611,7 +616,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.code !== 'ENOENT') { if ((err as any)?.code !== 'ENOENT') {
throw err throw err
} }
} }
@@ -638,10 +643,11 @@ describe('git-auth-helper tests', () => {
expect(gitConfigContent.indexOf('http.')).toBeLessThan(0) expect(gitConfigContent.indexOf('http.')).toBeLessThan(0)
}) })
const removeGlobalAuth_removesOverride = 'removeGlobalAuth removes override' const removeGlobalConfig_removesOverride =
it(removeGlobalAuth_removesOverride, async () => { 'removeGlobalConfig removes override'
it(removeGlobalConfig_removesOverride, async () => {
// Arrange // Arrange
await setup(removeGlobalAuth_removesOverride) await setup(removeGlobalConfig_removesOverride)
const authHelper = gitAuthHelper.createAuthHelper(git, settings) const authHelper = gitAuthHelper.createAuthHelper(git, settings)
await authHelper.configureAuth() await authHelper.configureAuth()
await authHelper.configureGlobalAuth() await authHelper.configureGlobalAuth()
@@ -650,7 +656,7 @@ describe('git-auth-helper tests', () => {
await fs.promises.stat(path.join(git.env['HOME'], '.gitconfig')) await fs.promises.stat(path.join(git.env['HOME'], '.gitconfig'))
// Act // Act
await authHelper.removeGlobalAuth() await authHelper.removeGlobalConfig()
// Assert // Assert
expect(git.env['HOME']).toBeUndefined() expect(git.env['HOME']).toBeUndefined()
@@ -658,7 +664,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.code !== 'ENOENT') { if ((err as any)?.code !== 'ENOENT') {
throw err throw err
} }
} }
@@ -764,13 +770,15 @@ async function setup(testName: string): Promise<void> {
submodules: false, submodules: false,
nestedSubmodules: false, nestedSubmodules: false,
persistCredentials: true, persistCredentials: true,
ref: 'refs/heads/master', ref: 'refs/heads/main',
repositoryName: 'my-repo', repositoryName: 'my-repo',
repositoryOwner: 'my-org', repositoryOwner: 'my-org',
repositoryPath: '', repositoryPath: '',
sshKey: sshPath ? 'some ssh private key' : '', sshKey: sshPath ? 'some ssh private key' : '',
sshKnownHosts: '', sshKnownHosts: '',
sshStrict: true sshStrict: true,
workflowOrganizationId: 123456,
setSafeDirectory: true
} }
} }
+31 -15
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,6 +43,11 @@ 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
}) })
@@ -67,8 +72,8 @@ describe('input-helper tests', () => {
jest.restoreAllMocks() jest.restoreAllMocks()
}) })
it('sets defaults', () => { it('sets defaults', async () => {
const settings: IGitSourceSettings = inputHelper.getInputs() const settings: IGitSourceSettings = await 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)
@@ -80,13 +85,14 @@ describe('input-helper tests', () => {
expect(settings.repositoryName).toBe('some-repo') expect(settings.repositoryName).toBe('some-repo')
expect(settings.repositoryOwner).toBe('some-owner') expect(settings.repositoryOwner).toBe('some-owner')
expect(settings.repositoryPath).toBe(gitHubWorkspace) expect(settings.repositoryPath).toBe(gitHubWorkspace)
expect(settings.setSafeDirectory).toBe(true)
}) })
it('qualifies ref', () => { it('qualifies ref', async () => {
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 = inputHelper.getInputs() const settings: IGitSourceSettings = await 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')
@@ -95,32 +101,42 @@ describe('input-helper tests', () => {
} }
}) })
it('requires qualified repo', () => { it('requires qualified repo', async () => {
inputs.repository = 'some-unqualified-repo' inputs.repository = 'some-unqualified-repo'
assert.throws(() => { try {
inputHelper.getInputs() await inputHelper.getInputs()
}, /Invalid repository 'some-unqualified-repo'/) throw 'should not reach here'
} catch (err) {
expect(`(${(err as any).message}`).toMatch(
"Invalid repository 'some-unqualified-repo'"
)
}
}) })
it('roots path', () => { it('roots path', async () => {
inputs.path = 'some-directory/some-subdirectory' inputs.path = 'some-directory/some-subdirectory'
const settings: IGitSourceSettings = inputHelper.getInputs() const settings: IGitSourceSettings = await 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', () => { it('sets ref to empty when explicit sha', async () => {
inputs.ref = '1111111111222222222233333333334444444444' inputs.ref = '1111111111222222222233333333334444444444'
const settings: IGitSourceSettings = inputHelper.getInputs() const settings: IGitSourceSettings = await 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', () => { it('sets sha to empty when explicit ref', async () => {
inputs.ref = 'refs/heads/some-other-ref' inputs.ref = 'refs/heads/some-other-ref'
const settings: IGitSourceSettings = inputHelper.getInputs() const settings: IGitSourceSettings = await 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)
})
}) })
+1 -1
View File
@@ -2,5 +2,5 @@
mkdir override-git-version mkdir override-git-version
cd override-git-version cd override-git-version
echo @echo override git version 1.2.3 > git.cmd echo @echo override git version 1.2.3 > git.cmd
echo ::add-path::%CD% echo "%CD%" >> $GITHUB_PATH
cd .. cd ..
+1 -1
View File
@@ -5,5 +5,5 @@ cd override-git-version
echo "#!/bin/sh" > git echo "#!/bin/sh" > git
echo "echo override git version 1.2.3" >> git echo "echo override git version 1.2.3" >> git
chmod +x git chmod +x git
echo "::add-path::$(pwd)" echo "$(pwd)" >> $GITHUB_PATH
cd .. cd ..
+5 -3
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.message).toBe('Arg git cannot be empty') expect((err as any)?.message).toBe('Arg git cannot be empty')
} }
}) })
@@ -25,7 +25,9 @@ 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.message).toBe('Args ref and commit cannot both be empty') expect((err as any)?.message).toBe(
'Args ref and commit cannot both be empty'
)
} }
}) })
@@ -102,7 +104,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.message).toBe( expect((err as any)?.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"
) )
} }
+1 -1
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 error = err as Error
} }
expect(error.message).toBe('some error 3') expect(error.message).toBe('some error 3')
expect(attempts).toBe(3) expect(attempts).toBe(3)
+1 -1
View File
@@ -20,5 +20,5 @@ else
# Verify auth token # Verify auth token
cd basic cd basic
git fetch --no-tags --depth=1 origin +refs/heads/master:refs/remotes/origin/master git fetch --no-tags --depth=1 origin +refs/heads/main:refs/remotes/origin/main
fi fi
+3
View File
@@ -68,6 +68,9 @@ inputs:
When the `ssh-key` input is not provided, SSH URLs beginning with `git@github.com:` are When the `ssh-key` input is not provided, SSH URLs beginning with `git@github.com:` are
converted to HTTPS. converted to HTTPS.
default: false default: false
set-safe-directory:
description: Add repository path as safe.directory for Git global config by running `git config --global --add safe.directory <path>`
default: true
runs: runs:
using: node12 using: node12
main: dist/index.js main: dist/index.js
+2 -2
View File
@@ -24,7 +24,7 @@ We want to take this opportunity to make behavioral changes, from v1. This docum
description: > description: >
The branch, tag or SHA to checkout. When checking out the repository that 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 triggered a workflow, this defaults to the reference or SHA for that
event. Otherwise, defaults to `master`. event. Otherwise, uses the default branch.
token: token:
description: > description: >
Personal access token (PAT) used to fetch the repository. The PAT is configured Personal access token (PAT) used to fetch the repository. The PAT is configured
@@ -277,7 +277,7 @@ Note:
### Branching strategy and release tags ### Branching strategy and release tags
- Create a servicing branch for V1: `releases/v1` - Create a servicing branch for V1: `releases/v1`
- Merge the changes into `master` - Merge the changes into the default branch
- Release using a new tag `preview` - Release using a new tag `preview`
- When stable, release using a new tag `v2` - When stable, release using a new tag `v2`
+7817 -753
View File
File diff suppressed because one or more lines are too long
+11683 -4731
View File
File diff suppressed because it is too large Load Diff
+16 -13
View File
@@ -1,6 +1,6 @@
{ {
"name": "checkout", "name": "checkout",
"version": "2.0.2", "version": "2.6.0",
"description": "checkout action", "description": "checkout action",
"main": "lib/main.js", "main": "lib/main.js",
"scripts": { "scripts": {
@@ -8,7 +8,9 @@
"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",
@@ -26,27 +28,28 @@
}, },
"homepage": "https://github.com/actions/checkout#readme", "homepage": "https://github.com/actions/checkout#readme",
"dependencies": { "dependencies": {
"@actions/core": "^1.1.3", "@actions/core": "^1.10.0",
"@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.1.2",
"@actions/tool-cache": "^1.1.2", "@actions/tool-cache": "^1.1.2",
"uuid": "^3.3.3" "uuid": "^3.3.3"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^24.0.23", "@types/jest": "^27.0.2",
"@types/node": "^12.7.12", "@types/node": "^12.7.12",
"@types/uuid": "^3.4.6", "@types/uuid": "^3.4.6",
"@typescript-eslint/parser": "^2.8.0", "@typescript-eslint/eslint-plugin": "^5.45.0",
"@typescript-eslint/parser": "^5.45.0",
"@zeit/ncc": "^0.20.5", "@zeit/ncc": "^0.20.5",
"eslint": "^5.16.0", "eslint": "^7.32.0",
"eslint-plugin-github": "^2.0.0", "eslint-plugin-github": "^4.3.2",
"eslint-plugin-jest": "^22.21.0", "eslint-plugin-jest": "^25.7.0",
"jest": "^24.9.0", "jest": "^27.3.0",
"jest-circus": "^24.9.0", "jest-circus": "^27.3.0",
"js-yaml": "^3.13.1", "js-yaml": "^3.13.1",
"prettier": "^1.19.1", "prettier": "^1.19.1",
"ts-jest": "^24.2.0", "ts-jest": "^27.0.7",
"typescript": "^3.6.4" "typescript": "^4.4.4"
} }
} }
+9 -6
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.code === 'ENOENT') { if ((error as any)?.code === 'ENOENT') {
if (!required) { if (!required) {
return false return false
} }
@@ -18,7 +18,8 @@ export function directoryExistsSync(path: string, required?: boolean): boolean {
} }
throw new Error( throw new Error(
`Encountered an error when checking whether path '${path}' exists: ${error.message}` `Encountered an error when checking whether path '${path}' exists: ${(error as any)
?.message ?? error}`
) )
} }
@@ -39,12 +40,13 @@ export function existsSync(path: string): boolean {
try { try {
fs.statSync(path) fs.statSync(path)
} catch (error) { } catch (error) {
if (error.code === 'ENOENT') { if ((error as any)?.code === 'ENOENT') {
return false return false
} }
throw new Error( throw new Error(
`Encountered an error when checking whether path '${path}' exists: ${error.message}` `Encountered an error when checking whether path '${path}' exists: ${(error as any)
?.message ?? error}`
) )
} }
@@ -60,12 +62,13 @@ export function fileExistsSync(path: string): boolean {
try { try {
stats = fs.statSync(path) stats = fs.statSync(path)
} catch (error) { } catch (error) {
if (error.code === 'ENOENT') { if ((error as any)?.code === 'ENOENT') {
return false return false
} }
throw new Error( throw new Error(
`Encountered an error when checking whether path '${path}' exists: ${error.message}` `Encountered an error when checking whether path '${path}' exists: ${(error as any)
?.message ?? error}`
) )
} }
+51 -27
View File
@@ -19,8 +19,9 @@ export interface IGitAuthHelper {
configureAuth(): Promise<void> configureAuth(): Promise<void>
configureGlobalAuth(): Promise<void> configureGlobalAuth(): Promise<void>
configureSubmoduleAuth(): Promise<void> configureSubmoduleAuth(): Promise<void>
configureTempGlobalConfig(): Promise<string>
removeAuth(): Promise<void> removeAuth(): Promise<void>
removeGlobalAuth(): Promise<void> removeGlobalConfig(): Promise<void>
} }
export function createAuthHelper( export function createAuthHelper(
@@ -37,7 +38,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 insteadOfValue: string private readonly insteadOfValues: string[] = []
private sshCommand = '' private sshCommand = ''
private sshKeyPath = '' private sshKeyPath = ''
private sshKnownHostsPath = '' private sshKnownHostsPath = ''
@@ -45,7 +46,7 @@ class GitAuthHelper {
constructor( constructor(
gitCommandManager: IGitCommandManager, gitCommandManager: IGitCommandManager,
gitSourceSettings?: IGitSourceSettings gitSourceSettings: IGitSourceSettings | undefined
) { ) {
this.git = gitCommandManager this.git = gitCommandManager
this.settings = gitSourceSettings || (({} as unknown) as IGitSourceSettings) this.settings = gitSourceSettings || (({} as unknown) as IGitSourceSettings)
@@ -63,7 +64,12 @@ 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.insteadOfValue = `git@${serverUrl.hostname}:` this.insteadOfValues.push(`git@${serverUrl.hostname}:`)
if (this.settings.workflowOrganizationId) {
this.insteadOfValues.push(
`org-${this.settings.workflowOrganizationId}@github.com:`
)
}
} }
async configureAuth(): Promise<void> { async configureAuth(): Promise<void> {
@@ -75,7 +81,11 @@ class GitAuthHelper {
await this.configureToken() await this.configureToken()
} }
async configureGlobalAuth(): Promise<void> { async configureTempGlobalConfig(): Promise<string> {
// Already setup global config
if (this.temporaryHomePath?.length > 0) {
return path.join(this.temporaryHomePath, '.gitconfig')
}
// Create a temp home directory // Create a temp home directory
const runnerTemp = process.env['RUNNER_TEMP'] || '' const runnerTemp = process.env['RUNNER_TEMP'] || ''
assert.ok(runnerTemp, 'RUNNER_TEMP is not defined') assert.ok(runnerTemp, 'RUNNER_TEMP is not defined')
@@ -94,7 +104,7 @@ class GitAuthHelper {
await fs.promises.stat(gitConfigPath) await fs.promises.stat(gitConfigPath)
configExists = true configExists = true
} catch (err) { } catch (err) {
if (err.code !== 'ENOENT') { if ((err as any)?.code !== 'ENOENT') {
throw err throw err
} }
} }
@@ -105,20 +115,28 @@ class GitAuthHelper {
await fs.promises.writeFile(newGitConfigPath, '') await fs.promises.writeFile(newGitConfigPath, '')
} }
try { // Override HOME
// Override HOME core.info(
core.info( `Temporarily overriding HOME='${this.temporaryHomePath}' before making global git config changes`
`Temporarily overriding HOME='${this.temporaryHomePath}' before making global git config changes` )
) this.git.setEnvironmentVariable('HOME', this.temporaryHomePath)
this.git.setEnvironmentVariable('HOME', this.temporaryHomePath)
return newGitConfigPath
}
async configureGlobalAuth(): Promise<void> {
// 'configureTempGlobalConfig' noops if already set, just returns the path
const newGitConfigPath = await this.configureTempGlobalConfig()
try {
// Configure the token // Configure the token
await this.configureToken(newGitConfigPath, true) await this.configureToken(newGitConfigPath, true)
// 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) {
await this.git.config(this.insteadOfKey, this.insteadOfValue, true) for (const insteadOfValue of this.insteadOfValues) {
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
@@ -139,7 +157,8 @@ class GitAuthHelper {
// by process creation audit events, which are commonly logged. For more information, // by process creation audit events, which are commonly logged. For more information,
// refer to https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/manage/component-updates/command-line-process-auditing // refer to https://docs.microsoft.com/en-us/windows-server/identity/ad-ds/manage/component-updates/command-line-process-auditing
const output = await this.git.submoduleForeach( const output = await this.git.submoduleForeach(
`git config --local '${this.tokenConfigKey}' '${this.tokenPlaceholderConfigValue}' && git config --local --show-origin --name-only --get-regexp remote.origin.url`, // wrap the pipeline in quotes to make sure it's handled properly by submoduleForeach, rather than just the first part of the pipeline
`sh -c "git config --local '${this.tokenConfigKey}' '${this.tokenPlaceholderConfigValue}' && git config --local --show-origin --name-only --get-regexp remote.origin.url"`,
this.settings.nestedSubmodules this.settings.nestedSubmodules
) )
@@ -148,7 +167,7 @@ class GitAuthHelper {
output.match(/(?<=(^|\n)file:)[^\t]+(?=\tremote\.origin\.url)/g) || [] output.match(/(?<=(^|\n)file:)[^\t]+(?=\tremote\.origin\.url)/g) || []
for (const configPath of configPaths) { for (const configPath of configPaths) {
core.debug(`Replacing token placeholder in '${configPath}'`) core.debug(`Replacing token placeholder in '${configPath}'`)
this.replaceTokenPlaceholder(configPath) await this.replaceTokenPlaceholder(configPath)
} }
if (this.settings.sshKey) { if (this.settings.sshKey) {
@@ -159,10 +178,12 @@ class GitAuthHelper {
) )
} else { } else {
// Configure HTTPS instead of SSH // Configure HTTPS instead of SSH
await this.git.submoduleForeach( for (const insteadOfValue of this.insteadOfValues) {
`git config --local '${this.insteadOfKey}' '${this.insteadOfValue}'`, await this.git.submoduleForeach(
this.settings.nestedSubmodules `git config --local --add '${this.insteadOfKey}' '${insteadOfValue}'`,
) this.settings.nestedSubmodules
)
}
} }
} }
} }
@@ -172,10 +193,12 @@ class GitAuthHelper {
await this.removeToken() await this.removeToken()
} }
async removeGlobalAuth(): Promise<void> { async removeGlobalConfig(): Promise<void> {
core.debug(`Unsetting HOME override`) if (this.temporaryHomePath?.length > 0) {
this.git.removeEnvironmentVariable('HOME') core.debug(`Unsetting HOME override`)
await io.rmRF(this.temporaryHomePath) this.git.removeEnvironmentVariable('HOME')
await io.rmRF(this.temporaryHomePath)
}
} }
private async configureSsh(): Promise<void> { private async configureSsh(): Promise<void> {
@@ -213,7 +236,7 @@ class GitAuthHelper {
await fs.promises.readFile(userKnownHostsPath) await fs.promises.readFile(userKnownHostsPath)
).toString() ).toString()
} catch (err) { } catch (err) {
if (err.code !== 'ENOENT') { if ((err as any)?.code !== 'ENOENT') {
throw err throw err
} }
} }
@@ -224,7 +247,7 @@ class GitAuthHelper {
if (this.settings.sshKnownHosts) { if (this.settings.sshKnownHosts) {
knownHosts += `# Begin from input known hosts\n${this.settings.sshKnownHosts}\n# end from input known hosts\n` knownHosts += `# Begin from input known hosts\n${this.settings.sshKnownHosts}\n# end from input known hosts\n`
} }
knownHosts += `# Begin implicitly added github.com\ngithub.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==\n# End implicitly added github.com\n` knownHosts += `# Begin implicitly added github.com\ngithub.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=\n# End implicitly added github.com\n`
this.sshKnownHostsPath = path.join(runnerTemp, `${uniqueId}_known_hosts`) this.sshKnownHostsPath = path.join(runnerTemp, `${uniqueId}_known_hosts`)
stateHelper.setSshKnownHostsPath(this.sshKnownHostsPath) stateHelper.setSshKnownHostsPath(this.sshKnownHostsPath)
await fs.promises.writeFile(this.sshKnownHostsPath, knownHosts) await fs.promises.writeFile(this.sshKnownHostsPath, knownHosts)
@@ -302,7 +325,7 @@ class GitAuthHelper {
try { try {
await io.rmRF(keyPath) await io.rmRF(keyPath)
} catch (err) { } catch (err) {
core.debug(err.message) core.debug(`${(err as any)?.message ?? err}`)
core.warning(`Failed to remove SSH key '${keyPath}'`) core.warning(`Failed to remove SSH key '${keyPath}'`)
} }
} }
@@ -343,7 +366,8 @@ class GitAuthHelper {
const pattern = regexpHelper.escape(configKey) const pattern = regexpHelper.escape(configKey)
await this.git.submoduleForeach( await this.git.submoduleForeach(
`git config --local --name-only --get-regexp '${pattern}' && git config --local --unset-all '${configKey}' || :`, // wrap the pipeline in quotes to make sure it's handled properly by submoduleForeach, rather than just the first part of the pipeline
`sh -c "git config --local --name-only --get-regexp '${pattern}' && git config --local --unset-all '${configKey}' || :"`,
true true
) )
} }
+19 -13
View File
@@ -21,7 +21,8 @@ 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>
@@ -31,7 +32,7 @@ export interface IGitCommandManager {
isDetached(): Promise<boolean> isDetached(): Promise<boolean>
lfsFetch(ref: string): Promise<void> lfsFetch(ref: string): Promise<void>
lfsInstall(): Promise<void> lfsInstall(): Promise<void>
log1(): Promise<string> log1(format?: string): Promise<string>
remoteAdd(remoteName: string, remoteUrl: string): Promise<void> remoteAdd(remoteName: string, remoteUrl: string): Promise<void>
removeEnvironmentVariable(name: string): void removeEnvironmentVariable(name: string): void
revParse(ref: string): Promise<string> revParse(ref: string): Promise<string>
@@ -140,14 +141,15 @@ class GitCommandManager {
async config( async config(
configKey: string, configKey: string,
configValue: string, configValue: string,
globalConfig?: boolean globalConfig?: boolean,
add?: boolean
): Promise<void> { ): Promise<void> {
await this.execGit([ const args: string[] = ['config', globalConfig ? '--global' : '--local']
'config', if (add) {
globalConfig ? '--global' : '--local', args.push('--add')
configKey, }
configValue args.push(...[configKey, configValue])
]) await this.execGit(args)
} }
async configExists( async configExists(
@@ -254,8 +256,10 @@ class GitCommandManager {
await this.execGit(['lfs', 'install', '--local']) await this.execGit(['lfs', 'install', '--local'])
} }
async log1(): Promise<string> { async log1(format?: string): Promise<string> {
const output = await this.execGit(['log', '-1']) var args = format ? ['log', '-1', format] : ['log', '-1']
var silent = format ? false : true
const output = await this.execGit(args, false, silent)
return output.stdout return output.stdout
} }
@@ -270,7 +274,7 @@ class GitCommandManager {
/** /**
* Resolves a ref to a SHA. For a branch or lightweight tag, the commit SHA is returned. * Resolves a ref to a SHA. For a branch or lightweight tag, the commit SHA is returned.
* For an annotated tag, the tag SHA is returned. * For an annotated tag, the tag SHA is returned.
* @param {string} ref For example: 'refs/heads/master' or '/refs/tags/v1' * @param {string} ref For example: 'refs/heads/main' or '/refs/tags/v1'
* @returns {Promise<string>} * @returns {Promise<string>}
*/ */
async revParse(ref: string): Promise<string> { async revParse(ref: string): Promise<string> {
@@ -390,7 +394,8 @@ class GitCommandManager {
private async execGit( private async execGit(
args: string[], args: string[],
allowAllExitCodes = false allowAllExitCodes = false,
silent = false
): Promise<GitOutput> { ): Promise<GitOutput> {
fshelper.directoryExistsSync(this.workingDirectory, true) fshelper.directoryExistsSync(this.workingDirectory, true)
@@ -409,6 +414,7 @@ class GitCommandManager {
const options = { const options = {
cwd: this.workingDirectory, cwd: this.workingDirectory,
env, env,
silent,
ignoreReturnCode: allowAllExitCodes, ignoreReturnCode: allowAllExitCodes,
listeners: { listeners: {
stdout: (data: Buffer) => { stdout: (data: Buffer) => {
+3 -1
View File
@@ -39,7 +39,9 @@ export async function prepareExistingDirectory(
try { try {
await io.rmRF(lockPath) await io.rmRF(lockPath)
} catch (error) { } catch (error) {
core.debug(`Unable to delete '${lockPath}'. ${error.message}`) core.debug(
`Unable to delete '${lockPath}'. ${(error as any)?.message ?? error}`
)
} }
} }
+129 -86
View File
@@ -36,68 +36,94 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
const git = await getGitCommandManager(settings) const git = await getGitCommandManager(settings)
core.endGroup() core.endGroup()
// Prepare existing directory, otherwise recreate let authHelper: gitAuthHelper.IGitAuthHelper | null = null
if (isExisting) { try {
await gitDirectoryHelper.prepareExistingDirectory( if (git) {
git, authHelper = gitAuthHelper.createAuthHelper(git, settings)
settings.repositoryPath, if (settings.setSafeDirectory) {
repositoryUrl, // Setup the repository path as a safe directory, so if we pass this into a container job with a different user it doesn't fail
settings.clean, // Otherwise all git commands we run in a container fail
settings.ref await authHelper.configureTempGlobalConfig()
) core.info(
} `Adding repository directory to the temporary git global config as a safe directory`
)
if (!git) { await git
// Downloading using REST API .config('safe.directory', settings.repositoryPath, true, true)
core.info(`The repository will be downloaded using the GitHub REST API`) .catch(error => {
core.info( core.info(
`To create a local Git repository instead, add Git ${gitCommandManager.MinimumGitVersion} or higher to the PATH` `Failed to initialize safe directory with error: ${error}`
) )
if (settings.submodules) { })
throw new Error(
`Input 'submodules' not supported when falling back to download using the GitHub REST API. To create a local Git repository instead, add Git ${gitCommandManager.MinimumGitVersion} or higher to the PATH.` stateHelper.setSafeDirectory()
) }
} else if (settings.sshKey) { }
throw new Error(
`Input 'ssh-key' not supported when falling back to download using the GitHub REST API. To create a local Git repository instead, add Git ${gitCommandManager.MinimumGitVersion} or higher to the PATH.` // Prepare existing directory, otherwise recreate
if (isExisting) {
await gitDirectoryHelper.prepareExistingDirectory(
git,
settings.repositoryPath,
repositoryUrl,
settings.clean,
settings.ref
) )
} }
await githubApiHelper.downloadRepository( if (!git) {
settings.authToken, // Downloading using REST API
settings.repositoryOwner, core.info(`The repository will be downloaded using the GitHub REST API`)
settings.repositoryName, core.info(
settings.ref, `To create a local Git repository instead, add Git ${gitCommandManager.MinimumGitVersion} or higher to the PATH`
settings.commit, )
settings.repositoryPath if (settings.submodules) {
) throw new Error(
return `Input 'submodules' not supported when falling back to download using the GitHub REST API. To create a local Git repository instead, add Git ${gitCommandManager.MinimumGitVersion} or higher to the PATH.`
} )
} else if (settings.sshKey) {
throw new Error(
`Input 'ssh-key' not supported when falling back to download using the GitHub REST API. To create a local Git repository instead, add Git ${gitCommandManager.MinimumGitVersion} or higher to the PATH.`
)
}
// Save state for POST action await githubApiHelper.downloadRepository(
stateHelper.setRepositoryPath(settings.repositoryPath) settings.authToken,
settings.repositoryOwner,
settings.repositoryName,
settings.ref,
settings.commit,
settings.repositoryPath
)
return
}
// Initialize the repository // Save state for POST action
if ( stateHelper.setRepositoryPath(settings.repositoryPath)
!fsHelper.directoryExistsSync(path.join(settings.repositoryPath, '.git'))
) { // Initialize the repository
core.startGroup('Initializing the repository') if (
await git.init() !fsHelper.directoryExistsSync(path.join(settings.repositoryPath, '.git'))
await git.remoteAdd('origin', repositoryUrl) ) {
core.startGroup('Initializing the repository')
await git.init()
await git.remoteAdd('origin', repositoryUrl)
core.endGroup()
}
// Disable automatic garbage collection
core.startGroup('Disabling automatic garbage collection')
if (!(await git.tryDisableAutomaticGarbageCollection())) {
core.warning(
`Unable to turn off git automatic garbage collection. The git fetch operation may trigger garbage collection and cause a delay.`
)
}
core.endGroup() core.endGroup()
}
// Disable automatic garbage collection // If we didn't initialize it above, do it now
core.startGroup('Disabling automatic garbage collection') if (!authHelper) {
if (!(await git.tryDisableAutomaticGarbageCollection())) { authHelper = gitAuthHelper.createAuthHelper(git, settings)
core.warning( }
`Unable to turn off git automatic garbage collection. The git fetch operation may trigger garbage collection and cause a delay.`
)
}
core.endGroup()
const authHelper = gitAuthHelper.createAuthHelper(git, settings)
try {
// Configure auth // Configure auth
core.startGroup('Setting up auth') core.startGroup('Setting up auth')
await authHelper.configureAuth() await authHelper.configureAuth()
@@ -170,40 +196,35 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
// Submodules // Submodules
if (settings.submodules) { if (settings.submodules) {
try { // Temporarily override global config
// Temporarily override global config core.startGroup('Setting up auth for fetching submodules')
core.startGroup('Setting up auth for fetching submodules') await authHelper.configureGlobalAuth()
await authHelper.configureGlobalAuth() core.endGroup()
core.endGroup()
// Checkout submodules // Checkout submodules
core.startGroup('Fetching submodules') core.startGroup('Fetching submodules')
await git.submoduleSync(settings.nestedSubmodules) await git.submoduleSync(settings.nestedSubmodules)
await git.submoduleUpdate( await git.submoduleUpdate(settings.fetchDepth, settings.nestedSubmodules)
settings.fetchDepth, await git.submoduleForeach(
settings.nestedSubmodules 'git config --local gc.auto 0',
) settings.nestedSubmodules
await git.submoduleForeach( )
'git config --local gc.auto 0', core.endGroup()
settings.nestedSubmodules
)
core.endGroup()
// Persist credentials // Persist credentials
if (settings.persistCredentials) { if (settings.persistCredentials) {
core.startGroup('Persisting credentials for submodules') core.startGroup('Persisting credentials for submodules')
await authHelper.configureSubmoduleAuth() await authHelper.configureSubmoduleAuth()
core.endGroup() core.endGroup()
}
} finally {
// Remove temporary global config override
await authHelper.removeGlobalAuth()
} }
} }
// Dump some info about the checked out commit // Get commit information
const commitInfo = await git.log1() const commitInfo = await git.log1()
// Log commit sha
await git.log1("--format='%H'")
// Check for incorrect pull request merge commit // Check for incorrect pull request merge commit
await refHelper.checkCommitInfo( await refHelper.checkCommitInfo(
settings.authToken, settings.authToken,
@@ -215,10 +236,13 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
) )
} finally { } finally {
// Remove auth // Remove auth
if (!settings.persistCredentials) { if (authHelper) {
core.startGroup('Removing auth') if (!settings.persistCredentials) {
await authHelper.removeAuth() core.startGroup('Removing auth')
core.endGroup() await authHelper.removeAuth()
core.endGroup()
}
authHelper.removeGlobalConfig()
} }
} }
} }
@@ -241,7 +265,26 @@ export async function cleanup(repositoryPath: string): Promise<void> {
// Remove auth // Remove auth
const authHelper = gitAuthHelper.createAuthHelper(git) const authHelper = gitAuthHelper.createAuthHelper(git)
await authHelper.removeAuth() try {
if (stateHelper.PostSetSafeDirectory) {
// Setup the repository path as a safe directory, so if we pass this into a container job with a different user it doesn't fail
// Otherwise all git commands we run in a container fail
await authHelper.configureTempGlobalConfig()
core.info(
`Adding repository directory to the temporary git global config as a safe directory`
)
await git
.config('safe.directory', repositoryPath, true, true)
.catch(error => {
core.info(`Failed to initialize safe directory with error: ${error}`)
})
}
await authHelper.removeAuth()
} finally {
await authHelper.removeGlobalConfig()
}
} }
async function getGitCommandManager( async function getGitCommandManager(
+10
View File
@@ -73,4 +73,14 @@ 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
/**
* Indicates whether to add repositoryPath as safe.directory in git global config
*/
setSafeDirectory: boolean
} }

Some files were not shown because too many files have changed in this diff Show More