Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f4c387e22b | ||
|
|
7b256c6763 | ||
|
|
c9e55219f5 | ||
|
|
9eeba4b77e | ||
|
|
9d5d72f348 | ||
|
|
1cb683f59c | ||
|
|
1faf939219 | ||
|
|
7e0f95e47a | ||
|
|
95951da3cb | ||
|
|
bdc764ff89 | ||
|
|
be5e352fa7 | ||
|
|
016e95b24b | ||
|
|
67a3a54916 | ||
|
|
ccbde630fa | ||
|
|
1d92969ea6 | ||
|
|
8098344c6b | ||
|
|
ff93395c55 | ||
|
|
f863e5cf3d | ||
|
|
7892dca28d | ||
|
|
2541b1294d | ||
|
|
0ffe6f9c55 |
38
.github/workflows/test.yml
vendored
38
.github/workflows/test.yml
vendored
@@ -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
|
||||||
17
.gitignore
vendored
17
.gitignore
vendored
@@ -2,3 +2,20 @@ __test__/_temp
|
|||||||
_temp/
|
_temp/
|
||||||
lib/
|
lib/
|
||||||
node_modules/
|
node_modules/
|
||||||
|
/dist/fs-helper.d.ts
|
||||||
|
/dist/git-auth-helper.d.ts
|
||||||
|
/dist/git-command-manager.d.ts
|
||||||
|
/dist/git-directory-helper.d.ts
|
||||||
|
/dist/git-source-provider.d.ts
|
||||||
|
/dist/git-source-settings.d.ts
|
||||||
|
/dist/git-version.d.ts
|
||||||
|
/dist/github-api-helper.d.ts
|
||||||
|
/dist/input-helper.d.ts
|
||||||
|
/dist/main.d.ts
|
||||||
|
/dist/misc/generate-docs.d.ts
|
||||||
|
/dist/ref-helper.d.ts
|
||||||
|
/dist/regexp-helper.d.ts
|
||||||
|
/dist/retry-helper.d.ts
|
||||||
|
/dist/state-helper.d.ts
|
||||||
|
/dist/url-helper.d.ts
|
||||||
|
/dist/workflow-context-helper.d.ts
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v3.0.2
|
||||||
|
- [Add input `set-safe-directory`](https://github.com/actions/checkout/pull/770)
|
||||||
|
|
||||||
## v3.0.1
|
## v3.0.1
|
||||||
- [Fixed an issue where checkout failed to run in container jobs due to the new git setting `safe.directory`](https://github.com/actions/checkout/pull/762)
|
- [Fixed an issue where checkout failed to run in container jobs due to the new git setting `safe.directory`](https://github.com/actions/checkout/pull/762)
|
||||||
- [Bumped various npm package versions](https://github.com/actions/checkout/pull/744)
|
- [Bumped various npm package versions](https://github.com/actions/checkout/pull/744)
|
||||||
|
|||||||
25
README.md
25
README.md
@@ -2,26 +2,28 @@
|
|||||||
<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
|
This is a fork of https://github.com/actions/checkout@v3
|
||||||
|
|
||||||
This action checks-out your repository under `$GITHUB_WORKSPACE`, so your workflow can access it.
|
# Build
|
||||||
|
|
||||||
Only a single commit is fetched by default, for the ref/SHA that triggered the workflow. Set `fetch-depth: 0` to fetch all history for all branches and tags. Refer [here](https://help.github.com/en/articles/events-that-trigger-workflows) to learn which commit `$GITHUB_SHA` points to for different events.
|
## Windows
|
||||||
|
|
||||||
The auth token is persisted in the local git config. This enables your scripts to run authenticated git commands. The token is removed during post-job cleanup. Set `persist-credentials: false` to opt-out.
|
ncc.cmd build .\src\main.ts
|
||||||
|
|
||||||
When Git 2.18 or higher is not in your PATH, falls back to the REST API to download the files.
|
|
||||||
|
|
||||||
# What's new
|
# What's new
|
||||||
|
|
||||||
- Updated to the node16 runtime by default
|
With this action it is possible to check out a repository located on a Gitea instance with subdirectories.
|
||||||
- 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.
|
|
||||||
|
Changed
|
||||||
|
`https://<domain>[:<port>]/<name>/<repository>`
|
||||||
|
to
|
||||||
|
`https://<domain>[:<port>]/<subpath>/<name>/<repository>`
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
|
|
||||||
<!-- start usage -->
|
<!-- start usage -->
|
||||||
```yaml
|
```yaml
|
||||||
- uses: actions/checkout@v3
|
- uses: https://gitea.com/ScMi1/checkout@v1
|
||||||
with:
|
with:
|
||||||
# Repository name with owner. For example, actions/checkout
|
# Repository name with owner. For example, actions/checkout
|
||||||
# Default: ${{ github.repository }}
|
# Default: ${{ github.repository }}
|
||||||
@@ -92,6 +94,11 @@ When Git 2.18 or higher is not in your PATH, falls back to the REST API to downl
|
|||||||
#
|
#
|
||||||
# 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 -->
|
||||||
|
|
||||||
|
|||||||
@@ -777,7 +777,8 @@ async function setup(testName: string): Promise<void> {
|
|||||||
sshKey: sshPath ? 'some ssh private key' : '',
|
sshKey: sshPath ? 'some ssh private key' : '',
|
||||||
sshKnownHosts: '',
|
sshKnownHosts: '',
|
||||||
sshStrict: true,
|
sshStrict: true,
|
||||||
workflowOrganizationId: 123456
|
workflowOrganizationId: 123456,
|
||||||
|
setSafeDirectory: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ 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', async () => {
|
it('qualifies ref', async () => {
|
||||||
|
|||||||
@@ -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: node16
|
using: node16
|
||||||
main: dist/index.js
|
main: dist/index.js
|
||||||
|
|||||||
33300
dist/index.js
vendored
33300
dist/index.js
vendored
File diff suppressed because one or more lines are too long
32849
package-lock.json
generated
32849
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -19,7 +19,7 @@ export interface IGitAuthHelper {
|
|||||||
configureAuth(): Promise<void>
|
configureAuth(): Promise<void>
|
||||||
configureGlobalAuth(): Promise<void>
|
configureGlobalAuth(): Promise<void>
|
||||||
configureSubmoduleAuth(): Promise<void>
|
configureSubmoduleAuth(): Promise<void>
|
||||||
configureTempGlobalConfig(repositoryPath?: string): Promise<string>
|
configureTempGlobalConfig(): Promise<string>
|
||||||
removeAuth(): Promise<void>
|
removeAuth(): Promise<void>
|
||||||
removeGlobalConfig(): Promise<void>
|
removeGlobalConfig(): Promise<void>
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ class GitAuthHelper {
|
|||||||
|
|
||||||
// Token auth header
|
// Token auth header
|
||||||
const serverUrl = urlHelper.getServerUrl()
|
const serverUrl = urlHelper.getServerUrl()
|
||||||
this.tokenConfigKey = `http.${serverUrl.origin}/.extraheader` // "origin" is SCHEME://HOSTNAME[:PORT]
|
this.tokenConfigKey = `http.${serverUrl.origin}${serverUrl.pathname}/.extraheader` // "origin" is SCHEME://HOSTNAME[:PORT]
|
||||||
const basicCredential = Buffer.from(
|
const basicCredential = Buffer.from(
|
||||||
`x-access-token:${this.settings.authToken}`,
|
`x-access-token:${this.settings.authToken}`,
|
||||||
'utf8'
|
'utf8'
|
||||||
@@ -63,7 +63,7 @@ class GitAuthHelper {
|
|||||||
this.tokenConfigValue = `AUTHORIZATION: basic ${basicCredential}`
|
this.tokenConfigValue = `AUTHORIZATION: basic ${basicCredential}`
|
||||||
|
|
||||||
// Instead of SSH URL
|
// Instead of SSH URL
|
||||||
this.insteadOfKey = `url.${serverUrl.origin}/.insteadOf` // "origin" is SCHEME://HOSTNAME[:PORT]
|
this.insteadOfKey = `url.${serverUrl.origin}${serverUrl.pathname}/.insteadOf` // "origin" is SCHEME://HOSTNAME[:PORT]
|
||||||
this.insteadOfValues.push(`git@${serverUrl.hostname}:`)
|
this.insteadOfValues.push(`git@${serverUrl.hostname}:`)
|
||||||
if (this.settings.workflowOrganizationId) {
|
if (this.settings.workflowOrganizationId) {
|
||||||
this.insteadOfValues.push(
|
this.insteadOfValues.push(
|
||||||
@@ -81,7 +81,7 @@ class GitAuthHelper {
|
|||||||
await this.configureToken()
|
await this.configureToken()
|
||||||
}
|
}
|
||||||
|
|
||||||
async configureTempGlobalConfig(repositoryPath?: string): Promise<string> {
|
async configureTempGlobalConfig(): Promise<string> {
|
||||||
// Already setup global config
|
// Already setup global config
|
||||||
if (this.temporaryHomePath?.length > 0) {
|
if (this.temporaryHomePath?.length > 0) {
|
||||||
return path.join(this.temporaryHomePath, '.gitconfig')
|
return path.join(this.temporaryHomePath, '.gitconfig')
|
||||||
@@ -121,21 +121,6 @@ class GitAuthHelper {
|
|||||||
)
|
)
|
||||||
this.git.setEnvironmentVariable('HOME', this.temporaryHomePath)
|
this.git.setEnvironmentVariable('HOME', this.temporaryHomePath)
|
||||||
|
|
||||||
// Setup the workspace 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
|
|
||||||
core.info(
|
|
||||||
`Adding working directory to the temporary git global config as a safe directory`
|
|
||||||
)
|
|
||||||
await this.git
|
|
||||||
.config(
|
|
||||||
'safe.directory',
|
|
||||||
repositoryPath ?? this.settings.repositoryPath,
|
|
||||||
true,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
.catch(error => {
|
|
||||||
core.info(`Failed to initialize safe directory with error: ${error}`)
|
|
||||||
})
|
|
||||||
return newGitConfigPath
|
return newGitConfigPath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -231,6 +231,7 @@ class GitCommandManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async init(): Promise<void> {
|
async init(): Promise<void> {
|
||||||
|
await this.execGit(['config', '--global', 'init.defaultBranch', 'main'])
|
||||||
await this.execGit(['init', this.workingDirectory])
|
await this.execGit(['init', this.workingDirectory])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,24 @@ export async function getSource(settings: IGitSourceSettings): Promise<void> {
|
|||||||
try {
|
try {
|
||||||
if (git) {
|
if (git) {
|
||||||
authHelper = gitAuthHelper.createAuthHelper(git, settings)
|
authHelper = gitAuthHelper.createAuthHelper(git, settings)
|
||||||
await authHelper.configureTempGlobalConfig()
|
if (settings.setSafeDirectory) {
|
||||||
|
// 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', settings.repositoryPath, true, true)
|
||||||
|
.catch(error => {
|
||||||
|
core.info(
|
||||||
|
`Failed to initialize safe directory with error: ${error}`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
stateHelper.setSafeDirectory()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare existing directory, otherwise recreate
|
// Prepare existing directory, otherwise recreate
|
||||||
@@ -249,7 +266,21 @@ export async function cleanup(repositoryPath: string): Promise<void> {
|
|||||||
// Remove auth
|
// Remove auth
|
||||||
const authHelper = gitAuthHelper.createAuthHelper(git)
|
const authHelper = gitAuthHelper.createAuthHelper(git)
|
||||||
try {
|
try {
|
||||||
await authHelper.configureTempGlobalConfig(repositoryPath)
|
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()
|
await authHelper.removeAuth()
|
||||||
} finally {
|
} finally {
|
||||||
await authHelper.removeGlobalConfig()
|
await authHelper.removeGlobalConfig()
|
||||||
|
|||||||
@@ -78,4 +78,9 @@ export interface IGitSourceSettings {
|
|||||||
* Organization ID for the currently running workflow (used for auth settings)
|
* Organization ID for the currently running workflow (used for auth settings)
|
||||||
*/
|
*/
|
||||||
workflowOrganizationId: number | undefined
|
workflowOrganizationId: number | undefined
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether to add repositoryPath as safe.directory in git global config
|
||||||
|
*/
|
||||||
|
setSafeDirectory: boolean
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,15 +23,15 @@ export async function getInputs(): Promise<IGitSourceSettings> {
|
|||||||
`${github.context.repo.owner}/${github.context.repo.repo}`
|
`${github.context.repo.owner}/${github.context.repo.repo}`
|
||||||
core.debug(`qualified repository = '${qualifiedRepository}'`)
|
core.debug(`qualified repository = '${qualifiedRepository}'`)
|
||||||
const splitRepository = qualifiedRepository.split('/')
|
const splitRepository = qualifiedRepository.split('/')
|
||||||
if (
|
// if (
|
||||||
splitRepository.length !== 2 ||
|
// splitRepository.length !== 2 ||
|
||||||
!splitRepository[0] ||
|
// !splitRepository[0] ||
|
||||||
!splitRepository[1]
|
// !splitRepository[1]
|
||||||
) {
|
// ) {
|
||||||
throw new Error(
|
// throw new Error(
|
||||||
`Invalid repository '${qualifiedRepository}'. Expected format {owner}/{repo}.`
|
// `Invalid repository '${qualifiedRepository}'. Expected format {owner}/{repo}.`
|
||||||
)
|
// )
|
||||||
}
|
// }
|
||||||
result.repositoryOwner = splitRepository[0]
|
result.repositoryOwner = splitRepository[0]
|
||||||
result.repositoryName = splitRepository[1]
|
result.repositoryName = splitRepository[1]
|
||||||
|
|
||||||
@@ -122,5 +122,8 @@ export async function getInputs(): Promise<IGitSourceSettings> {
|
|||||||
// Workflow organization ID
|
// Workflow organization ID
|
||||||
result.workflowOrganizationId = await workflowContextHelper.getOrganizationId()
|
result.workflowOrganizationId = await workflowContextHelper.getOrganizationId()
|
||||||
|
|
||||||
|
// Set safe.directory in git global config.
|
||||||
|
result.setSafeDirectory =
|
||||||
|
(core.getInput('set-safe-directory') || 'true').toUpperCase() === 'TRUE'
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,12 @@ export const IsPost = !!process.env['STATE_isPost']
|
|||||||
export const RepositoryPath =
|
export const RepositoryPath =
|
||||||
(process.env['STATE_repositoryPath'] as string) || ''
|
(process.env['STATE_repositoryPath'] as string) || ''
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The set-safe-directory for the POST action. The value is set if input: 'safe-directory' is set during the MAIN action.
|
||||||
|
*/
|
||||||
|
export const PostSetSafeDirectory =
|
||||||
|
(process.env['STATE_setSafeDirectory'] as string) === 'true'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The SSH key path for the POST action. The value is empty during the MAIN action.
|
* The SSH key path for the POST action. The value is empty during the MAIN action.
|
||||||
*/
|
*/
|
||||||
@@ -51,6 +57,13 @@ export function setSshKnownHostsPath(sshKnownHostsPath: string) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the sef-safe-directory input so the POST action can retrieve the value.
|
||||||
|
*/
|
||||||
|
export function setSafeDirectory() {
|
||||||
|
coreCommand.issueCommand('save-state', {name: 'setSafeDirectory'}, 'true')
|
||||||
|
}
|
||||||
|
|
||||||
// Publish a variable so that when the POST action runs, it can determine it should run the cleanup logic.
|
// Publish a variable so that when the POST action runs, it can determine it should run the cleanup logic.
|
||||||
// This is necessary since we don't have a separate entry point.
|
// This is necessary since we don't have a separate entry point.
|
||||||
if (!IsPost) {
|
if (!IsPost) {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export function getFetchUrl(settings: IGitSourceSettings): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// "origin" is SCHEME://HOSTNAME[:PORT]
|
// "origin" is SCHEME://HOSTNAME[:PORT]
|
||||||
return `${serviceUrl.origin}/${encodedOwner}/${encodedName}`
|
return `${serviceUrl.origin}${serviceUrl.pathname}/${encodedOwner}/${encodedName}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getServerUrl(): URL {
|
export function getServerUrl(): URL {
|
||||||
|
|||||||
Reference in New Issue
Block a user