mirror of
https://hub.psychoinformatics.de/actions/checkout-action.git
synced 2026-09-10 05:46:04 +00:00
This should be implementing the same semantics as the node.js based action.
220 lines
12 KiB
YAML
220 lines
12 KiB
YAML
name: checkout-action
|
|
description: GitHub Action for checking out a repository. (Simplified actions/checkout alternative that does not depend on Node.js.)
|
|
|
|
inputs:
|
|
token:
|
|
description: GitHub token for checking out a repository.
|
|
required: false
|
|
fetch-depth:
|
|
required: false
|
|
default: '1'
|
|
description: Number of commits to fetch. 0 indicates all history for all branches and tags.
|
|
|
|
# Note:
|
|
# - inputs.* should be manually mapped to INPUT_* due to https://github.com/actions/runner/issues/665
|
|
# - For context containing path, use GITHUB_*/RUNNER_* instead of github.*/runner.* due to https://github.com/actions/runner/issues/2185
|
|
runs:
|
|
using: composite
|
|
steps:
|
|
- run: |
|
|
# Checkout (non-Windows)
|
|
bail() {
|
|
printf '::error::checkout-action: %s\n' "$*"
|
|
exit 1
|
|
}
|
|
warn() {
|
|
printf '::warning::checkout-action: %s\n' "$*"
|
|
}
|
|
# Use binaries available at standard location to prevent path interception.
|
|
# On macOS and known Linux distributions:
|
|
# - /usr/bin/env and /bin/sh are always available.
|
|
# On macOS and known non-NixOS Linux distributions:
|
|
# - /bin/bash is available by default or when bash is installed by system package manager.
|
|
# - Required or optionally used tools are available in any of /bin:/usr/bin:/sbin:/usr/sbin
|
|
# by default or when installed by system package manager.
|
|
# Note that sed/awk (both not currently used in this action) are not always available by default,
|
|
# e.g.,:
|
|
# - no sed: nixos/nix, photon:1.0
|
|
# - no awk: opensuse/tumbleweed, nixos/nix, openmandriva/cooker, photon
|
|
# On NixOS:
|
|
# - bash and POSIX utilities are available at /run/current-system/sw/bin or /run/wrappers/bin.
|
|
# On nixos/nix image (which has no /etc/NIXOS), they are available at /root/.nix-profile/bin.
|
|
# - git is usually available at ~/.nix-profile/bin when installed by system package manager.
|
|
# See "Compatibility" section in README.md for partial list of tested distributions.
|
|
# git also uses binaries available at standard location by default:
|
|
# https://github.com/git/git/blob/v2.54.0/Makefile#L927-L935
|
|
# NB: Sync with resolve_path in src/*.sh and tools/ci/test-bash-func.sh.
|
|
resolve_path() {
|
|
for dir in /bin /usr/bin /sbin /usr/sbin; do
|
|
if [ -x "${dir}/$1" ]; then
|
|
printf '%s/%s\n' "${dir}" "$1"
|
|
return
|
|
fi
|
|
done
|
|
if [ -e /etc/NIXOS ] && [ -x /run/current-system/sw/bin/"$1" ]; then
|
|
printf '/run/current-system/sw/bin/%s\n' "$1"
|
|
elif [ -e /etc/NIXOS ] && [ -x /run/wrappers/bin/"$1" ]; then
|
|
printf '/run/wrappers/bin/%s\n' "$1"
|
|
elif [ -e /etc/nix ] && [ -x /root/.nix-profile/bin/"$1" ]; then
|
|
printf '/root/.nix-profile/bin/%s\n' "$1"
|
|
fi
|
|
}
|
|
# Install missing required tools from system package manager on Linux.
|
|
# See src/install-required-tools.sh for more.
|
|
if [ "${RUNNER_OS}" = 'Linux' ]; then
|
|
if ! command -v bash >/dev/null 2>&1 || ! command -v git >/dev/null 2>&1; then
|
|
/bin/sh "${GITHUB_ACTION_PATH:?}/src/install-required-tools.sh"
|
|
fi
|
|
fi
|
|
bash=$(resolve_path bash)
|
|
if [ -z "${bash}" ]; then
|
|
bash=$(command -v bash 2>/dev/null || :)
|
|
if [ -z "${bash}" ]; then
|
|
bail "this action requires bash"
|
|
elif [ -n "${HAS_TOKEN}" ]; then
|
|
bail "bash is unavailable at standard location; found ${bash}; aborting due to security reasons because 'token' input option is set"
|
|
else
|
|
warn "bash is unavailable at standard location; using ${bash}, but this may be blocked for security reasons in the future"
|
|
fi
|
|
fi
|
|
"${bash}" --noprofile --norc --posix "${GITHUB_ACTION_PATH:?}/src/main.sh"
|
|
# Unset environment variables that may unexpectedly affect sh/bash behavior.
|
|
# - Environment variables that may unexpectedly affect sh/bash behavior
|
|
# must be unset here.
|
|
# - Environment variables that also affect env command behavior must be
|
|
# replaced with harmless values in env field. e.g., LD_*, DYLD_*
|
|
# - For such environment variables for other commands, unset them in
|
|
# script as needed.
|
|
# We unset the followings here:
|
|
# - IFS, CDPATH, ENV, BASH_ENV, PS4, GLOBIGNORE, BASHOPTS, SHELLOPTS, FPATH:
|
|
# See:
|
|
# - https://github.com/sudo-project/sudo/blob/a40200a08a52515db4bc259c0153e7cd92f309ad/plugins/sudoers/env.c#L133
|
|
# - https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html#Invoked-with-unequal-effective-and-real-uid_002fgids
|
|
# - *builtin*, *[*, *printf*, *command*, *read*:
|
|
# Bash supports injecting function via environment variable:
|
|
# - Since CVE-2014-6271 fix: BASH_FUNC_func%%='() { ..; }'
|
|
# - Red Hat uses the different style in old versions (RHEL 5-7): BASH_FUNC_func()='() { ..; }'
|
|
# - Apple also uses the different style in old versions: __BASH_FUNC<func>()='() { ..; }'
|
|
# - Until CVE-2014-6271 fix: func='() { ..; }'
|
|
# This affects even when bash launched as /bin/sh (i.e., in POSIX mode).
|
|
# See tools/ci/test-bash-func.sh for known affected/unaffected builtins.
|
|
# We do the following to address this issue:
|
|
# - Unset all style of environment variables that may inject bash function
|
|
# for these builtins.
|
|
# The latter four are needed because builtin command may not be available
|
|
# in POSIX sh (i.e., scripts in action.yml and src/src/install-required-tools.sh,
|
|
# and credential helper in main.sh).
|
|
# Windows step removes all environment variables with value staring with '() {',
|
|
# and sudo does similar, but it is difficult to do the same thing correctly in
|
|
# a portable way. See tools/ci/test-list-bash-func-*.sh for details.
|
|
# - Use POSIX mode in bash scripts to reduce the number of affected builtins,
|
|
# and call affected builtins via "builtin" command.
|
|
# The uses of affected builtins are detected by tools/ci/test-bash-func.sh.
|
|
# NB: Sync with Windows step.
|
|
shell: '/usr/bin/env -u IFS -u CDPATH -u ENV -u BASH_ENV -u PS4 -u GLOBIGNORE -u BASHOPTS -u SHELLOPTS -u FPATH -u builtin -u BASH_FUNC_builtin%% -u BASH_FUNC_builtin() -u __BASH_FUNC<builtin>() -u [ -u BASH_FUNC_[%% -u BASH_FUNC_[() -u __BASH_FUNC<[>() -u printf -u BASH_FUNC_printf%% -u BASH_FUNC_printf() -u __BASH_FUNC<printf>() -u command -u BASH_FUNC_command%% -u BASH_FUNC_command() -u __BASH_FUNC<command>() -u read -u BASH_FUNC_read%% -u BASH_FUNC_read() -u __BASH_FUNC<read>() /bin/sh -eu {0}' # zizmor: ignore[misfeature] false positive
|
|
env:
|
|
# NB: Sync with Windows step.
|
|
INPUT_TOKEN: ${{ inputs.token }}
|
|
INPUT_FETCH_DEPTH: ${{ inputs.fetch-depth }}
|
|
# TODO: support in input options
|
|
INPUT_REPOSITORY: ${{ github.repository }}
|
|
INPUT_SERVER_URL: ${{ github.server_url }}
|
|
INPUT_SHA: ${{ github.sha }}
|
|
INPUT_REF: ${{ github.ref }}
|
|
HAS_TOKEN: ${{ inputs.token && '1' || '' }}
|
|
RUNNER_OS: ${{ runner.os }}
|
|
# Unset environment variables that may unexpectedly affect env/sh/bash/etc. behavior.
|
|
# Since these may also affect env command, they must be replaced with harmless values before it is called.
|
|
# for Linux
|
|
# Refs:
|
|
# - "Secure-execution mode" in https://man7.org/linux/man-pages/man8/ld.so.8.html
|
|
# - https://musl.libc.org/manual.html
|
|
LD_AUDIT: ''
|
|
LD_DEBUG: ''
|
|
LD_DEBUG_OUTPUT: ''
|
|
LD_DYNAMIC_WEAK: ''
|
|
LD_HWCAP_MASK: ''
|
|
LD_LIBRARY_PATH: ''
|
|
LD_ORIGIN_PATH: ''
|
|
LD_PRELOAD: ''
|
|
LD_PROFILE: ''
|
|
# for macOS
|
|
DYLD_INSERT_LIBRARIES: ''
|
|
DYLD_FRAMEWORK_PATH: ''
|
|
DYLD_LIBRARY_PATH: ''
|
|
DYLD_FALLBACK_FRAMEWORK_PATH: ''
|
|
DYLD_FALLBACK_LIBRARY_PATH: ''
|
|
DYLD_VERSIONED_FRAMEWORK_PATH: ''
|
|
DYLD_VERSIONED_LIBRARY_PATH: ''
|
|
if: runner.os != 'Windows'
|
|
# Use pwsh and retry on bash startup failure to work around windows-11-arm runner bug:
|
|
# https://github.com/actions/partner-runner-images/issues/169
|
|
- run: |
|
|
# Checkout (Windows)
|
|
Set-StrictMode -Version Latest
|
|
# Unset environment variables that may unexpectedly affect sh/bash behavior.
|
|
# See comment on shell field in action.yml for more.
|
|
# NB: Sync with it.
|
|
$remove_env = @('IFS','CDPATH','ENV','BASH_ENV','PS4','GLOBIGNORE','BASHOPTS','SHELLOPTS','FPATH')
|
|
foreach ($name in $remove_env) {
|
|
if (Test-Path -LiteralPath "Env:$name") { Remove-Item -LiteralPath "Env:\$name" }
|
|
}
|
|
# NB: Sync with tools/ci/test-bash-func-pwsh.ps1.
|
|
(Get-ChildItem Env:*) | ForEach-Object {
|
|
# -LiteralPath is important since BASH_FUNC_[%% is valid environment variable to override [.
|
|
if ($_.Value.StartsWith("() {")) { Remove-Item -LiteralPath "Env:\$($_.Key)" }
|
|
}
|
|
# Use binaries available at standard location to prevent path interception.
|
|
$bash = (Get-Command bash).Path
|
|
switch ($bash) {
|
|
"C:\Program Files\Git\bin\bash.exe" {} # default
|
|
"C:\msys64\usr\bin\bash.exe" {} # MSYS2
|
|
"C:\tools\cygwin\bin\bash.exe" {} # Cygwin
|
|
default {
|
|
if (Test-Path -LiteralPath "C:\Program Files\Git\bin\bash.exe") {
|
|
$bash = "C:\Program Files\Git\bin\bash.exe"
|
|
} elseif (Test-Path -LiteralPath "C:\msys64\usr\bin\bash.exe") {
|
|
$bash = "C:\msys64\usr\bin\bash.exe"
|
|
} elseif (Test-Path -LiteralPath "C:\tools\cygwin\bin\bash.exe") {
|
|
$bash = "C:\tools\cygwin\bin\bash.exe"
|
|
} elseif ("$bash" -eq "") {
|
|
Write-Output "::error::checkout-action: this action requires bash"
|
|
exit 1
|
|
} elseif ("$env:HAS_TOKEN" -ne "") {
|
|
Write-Output "::error::checkout-action: bash is unavailable at standard location; found $bash; aborting due to security reasons because 'token' input option is set"
|
|
exit 1
|
|
} else {
|
|
Write-Output "::warning::checkout-action: bash is unavailable at standard location; using $bash, but this may be blocked for security reasons in the future"
|
|
}
|
|
}
|
|
}
|
|
for ($i=1; $i -le 10; $i++) {
|
|
$prev_err_action = $ErrorActionPreference
|
|
$ErrorActionPreference = "Continue"
|
|
& "$bash" --noprofile --norc --posix "$env:GITHUB_ACTION_PATH\src\main.sh"
|
|
$code = $LASTEXITCODE
|
|
$ErrorActionPreference = "$prev_err_action"
|
|
if (Test-Path -LiteralPath "$env:USERPROFILE\.checkout-action-init") {
|
|
# If bash started successfully, src/main.sh creates init file.
|
|
Remove-Item -LiteralPath "$env:USERPROFILE\.checkout-action-init" -Force
|
|
exit $code
|
|
}
|
|
if ($i -lt 10) {
|
|
Write-Output "::warning::checkout-action: checkout failed due to bash startup failure (<https://github.com/actions/partner-runner-images/issues/169>); retrying..."
|
|
}
|
|
}
|
|
Write-Output "::error::checkout-action: checkout failed due to bash startup failure (<https://github.com/actions/partner-runner-images/issues/169>); this maybe resolved by re-running job"
|
|
exit 1
|
|
shell: pwsh
|
|
env:
|
|
# NB: Sync with non-Windows step.
|
|
INPUT_TOKEN: ${{ inputs.token }}
|
|
INPUT_FETCH_DEPTH: ${{ inputs.fetch-depth }}
|
|
# TODO: support in input options
|
|
INPUT_REPOSITORY: ${{ github.repository }}
|
|
INPUT_SERVER_URL: ${{ github.server_url }}
|
|
INPUT_SHA: ${{ github.sha }}
|
|
INPUT_REF: ${{ github.ref }}
|
|
HAS_TOKEN: ${{ inputs.token && '1' || '' }}
|
|
RUNNER_OS: ${{ runner.os }}
|
|
if: runner.os == 'Windows'
|