178 lines
5.4 KiB
YAML
178 lines
5.4 KiB
YAML
name: Reusable Prepare Workspace
|
||
|
||
on:
|
||
workflow_call:
|
||
inputs:
|
||
repo_url:
|
||
description: "Git 仓库地址"
|
||
required: true
|
||
type: string
|
||
git_sha:
|
||
description: "目标提交 SHA"
|
||
required: true
|
||
type: string
|
||
node_major:
|
||
description: "Node 主版本(例如 22)"
|
||
required: false
|
||
type: string
|
||
default: "22"
|
||
node_version:
|
||
description: "Node 精确版本(例如 22.12.0,优先于 node_major)"
|
||
required: false
|
||
type: string
|
||
default: ""
|
||
yarn_version:
|
||
description: "Yarn 版本(例如 stable 或 1.22.22)"
|
||
required: false
|
||
type: string
|
||
default: "stable"
|
||
nodejs_mirror:
|
||
description: "Node 二进制镜像地址"
|
||
required: false
|
||
type: string
|
||
default: "https://npmmirror.com/mirrors/node"
|
||
npm_registry:
|
||
description: "NPM 镜像地址"
|
||
required: false
|
||
type: string
|
||
default: "https://registry.npmmirror.com"
|
||
node_install_root:
|
||
description: "Node 安装缓存目录"
|
||
required: false
|
||
type: string
|
||
default: ""
|
||
run_commands:
|
||
description: "准备完成后执行的额外命令(多行 shell)"
|
||
required: false
|
||
type: string
|
||
default: ""
|
||
secrets:
|
||
SSH_PRIVATE_KEY:
|
||
required: false
|
||
REGISTRY_USERNAME:
|
||
required: false
|
||
REGISTRY_PASSWORD:
|
||
required: false
|
||
|
||
jobs:
|
||
prepare:
|
||
runs-on: ubuntu-latest
|
||
env:
|
||
REPO_URL: ${{ inputs.repo_url }}
|
||
GIT_SHA: ${{ inputs.git_sha }}
|
||
NODE_MAJOR: ${{ inputs.node_major }}
|
||
NODE_VERSION: ${{ inputs.node_version }}
|
||
YARN_VERSION: ${{ inputs.yarn_version }}
|
||
NODEJS_MIRROR: ${{ inputs.nodejs_mirror }}
|
||
NPM_REGISTRY: ${{ inputs.npm_registry }}
|
||
NODE_INSTALL_ROOT: ${{ inputs.node_install_root }}
|
||
RUN_COMMANDS: ${{ inputs.run_commands }}
|
||
steps:
|
||
- name: Prepare workspace (checkout + node/yarn)
|
||
run: |
|
||
set -euo pipefail
|
||
|
||
resolve_node_version() {
|
||
if [ -n "${NODE_VERSION}" ]; then
|
||
echo "${NODE_VERSION#v}"
|
||
return
|
||
fi
|
||
|
||
local resolved
|
||
resolved="$(curl -fsSL "${NODEJS_MIRROR}/index.tab" | awk -F'\t' -v major="${NODE_MAJOR}" '
|
||
NR > 1 && $1 ~ ("^v" major "\\.") { print substr($1, 2); exit }
|
||
')"
|
||
if [ -z "${resolved}" ]; then
|
||
echo "failed to resolve latest Node ${NODE_MAJOR}.x from ${NODEJS_MIRROR}"
|
||
exit 1
|
||
fi
|
||
echo "${resolved}"
|
||
}
|
||
|
||
if [ -z "${NODE_INSTALL_ROOT}" ]; then
|
||
NODE_INSTALL_ROOT="${HOME}/.local/node-ci"
|
||
fi
|
||
|
||
detect_arch() {
|
||
case "$(uname -m)" in
|
||
x86_64) echo "x64" ;;
|
||
aarch64 | arm64) echo "arm64" ;;
|
||
*)
|
||
echo "unsupported architecture: $(uname -m)"
|
||
exit 1
|
||
;;
|
||
esac
|
||
}
|
||
|
||
install_node() {
|
||
local target_version="$1"
|
||
local arch name url tarball install_dir bindir
|
||
arch="$(detect_arch)"
|
||
name="node-v${target_version}-linux-${arch}"
|
||
url="${NODEJS_MIRROR}/v${target_version}/${name}.tar.xz"
|
||
tarball="/tmp/${name}.tar.xz"
|
||
install_dir="${NODE_INSTALL_ROOT}/${name}"
|
||
bindir="${install_dir}/bin"
|
||
|
||
if [ ! -x "${bindir}/node" ]; then
|
||
mkdir -p "${NODE_INSTALL_ROOT}"
|
||
curl -fsSL "${url}" -o "${tarball}"
|
||
tar -xJf "${tarball}" -C "${NODE_INSTALL_ROOT}"
|
||
rm -f "${tarball}"
|
||
fi
|
||
|
||
export PATH="${bindir}:${PATH}"
|
||
}
|
||
|
||
ensure_node() {
|
||
local target_version node_version
|
||
target_version="$(resolve_node_version)"
|
||
|
||
if command -v node >/dev/null 2>&1; then
|
||
node_version="$(node -v | sed 's/^v//')"
|
||
if [ "${node_version}" = "${target_version}" ]; then
|
||
return
|
||
fi
|
||
fi
|
||
|
||
install_node "${target_version}"
|
||
|
||
node_version="$(node -v | sed 's/^v//')"
|
||
if [ "${node_version}" != "${target_version}" ]; then
|
||
echo "failed to switch to Node ${target_version}, current=${node_version}"
|
||
exit 1
|
||
fi
|
||
}
|
||
|
||
if [ ! -d .git ]; then
|
||
git clone "${REPO_URL}" .
|
||
fi
|
||
|
||
git fetch --all --tags --prune
|
||
git checkout -f "${GIT_SHA}"
|
||
|
||
ensure_node
|
||
|
||
npm config set registry "${NPM_REGISTRY}" >/dev/null 2>&1 || true
|
||
|
||
if ! command -v yarn >/dev/null 2>&1; then
|
||
corepack enable
|
||
export COREPACK_NPM_REGISTRY="${NPM_REGISTRY}"
|
||
corepack prepare "yarn@${YARN_VERSION}" --activate
|
||
fi
|
||
|
||
echo "Node: $(node -v)"
|
||
echo "Yarn: $(yarn -v)"
|
||
|
||
- name: Run extra commands
|
||
if: ${{ inputs.run_commands != '' }}
|
||
env:
|
||
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
|
||
REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
|
||
REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
|
||
run: |
|
||
set -euo pipefail
|
||
printf '%s\n' "${RUN_COMMANDS}" > /tmp/reusable-prepare-run.sh
|
||
chmod +x /tmp/reusable-prepare-run.sh
|
||
/tmp/reusable-prepare-run.sh
|