feat: 初始化项目,新增web项目ci脚本;

This commit is contained in:
2026-04-12 01:29:57 +08:00
commit e8458df680
2 changed files with 161 additions and 0 deletions

3
README.md Normal file
View File

@@ -0,0 +1,3 @@
# CI脚本项目
## ci/web-spa-deploy.yml: web项目构建、部署

158
ci/web-spa-deploy.yml Normal file
View File

@@ -0,0 +1,158 @@
# 公共可复用工作流workflow_call。调用方传入node_version、yarn_version、project_dir。
# 部署主机/用户/父路径、SSH 私钥从「调用方」仓库的 vars / secrets 读取(同仓 uses: ./... 时即本仓库配置)。
#
# 调用方 ci.yml 示例:
# jobs:
# build:
# uses: ./.gitea/workflows/node-spa-tar-deploy.reusable.yml@main
# with:
# node_version: "22.14.0"
# yarn_version: "1.22.22"
# project_dir: "chat-one-web"
# secrets: inherit
#
# 调用方「工作流 → 变量」DEPLOY_PATH、DEPLOY_HOST、DEPLOY_USER
# 调用方「工作流 → 密钥」SSH_PRIVATE_KEY
# 远端发布目录 = ${DEPLOY_PATH}/${project_dir}
name: Reusable Node SPA + tar deploy
on:
workflow_call:
inputs:
node_version:
description: "Node 完整版本号(如 22.14.0npmmirror linux-x64"
required: true
type: string
yarn_version:
description: "Yarn 1 版本号(如 1.22.22"
required: true
type: string
project_dir:
description: "站点子目录(相对 DEPLOY_PATH如 chat-one-web"
required: true
type: string
jobs:
build:
runs-on: ubuntu-latest
env:
DEPLOY_PATH: ${{ vars.DEPLOY_PATH }}
DEPLOY_HOST: ${{ vars.DEPLOY_HOST }}
DEPLOY_USER: ${{ vars.DEPLOY_USER }}
steps:
- name: Checkout
env:
TOKEN: ${{ github.token }}
run: |
set -e
export GIT_TERMINAL_PROMPT=0
if ! command -v git >/dev/null 2>&1; then
export DEBIAN_FRONTEND=noninteractive
shopt -s nullglob
for f in /etc/apt/sources.list /etc/apt/sources.list.d/debian.sources /etc/apt/sources.list.d/*.sources /etc/apt/sources.list.d/*.list; do
[ -f "$f" ] || continue
sed -i \
-e 's/deb.debian.org/mirrors.aliyun.com/g' \
-e 's/security.debian.org/mirrors.aliyun.com/g' \
"$f"
done
apt-get -o Acquire::http::Timeout=30 -o Acquire::https::Timeout=30 -o Acquire::Retries=2 update
apt-get install -y --no-install-recommends git
fi
SERVER="${{ github.server_url }}"
SERVER="${SERVER%/}"
REPO="${{ github.repository }}"
ORIGIN="${SERVER/https:\/\//https:\/\/oauth2:${TOKEN}@}"
ORIGIN="${ORIGIN/http:\/\//http:\/\/oauth2:${TOKEN}@}/${REPO}.git"
git init
git remote add origin "$ORIGIN"
git fetch --depth 1 origin "${{ github.sha }}"
git checkout -f "${{ github.sha }}"
- name: Install Node ${{ inputs.node_version }}
run: |
set -euo pipefail
NODE_VER="${{ inputs.node_version }}"
WANT="${NODE_VER#v}"
HAVE=""
if command -v node >/dev/null 2>&1; then
HAVE="$(node -v | sed 's/^v//')"
fi
if [ -n "$HAVE" ] && [ "$HAVE" = "$WANT" ]; then
echo "Node 已是 ${WANT}node -v: v${HAVE}),跳过下载安装"
node -v
exit 0
fi
ARCH="linux-x64"
NAME="node-v${WANT}-${ARCH}"
URL="https://npmmirror.com/mirrors/node/v${WANT}/${NAME}.tar.xz"
curl -fsSL "$URL" -o /tmp/node.tar.xz
mkdir -p /opt/node-ci
tar -xJf /tmp/node.tar.xz -C /opt/node-ci
BINDIR="/opt/node-ci/${NAME}/bin"
if [ -x "$BINDIR/node" ]; then
[ -n "${GITHUB_PATH:-}" ] && echo "$BINDIR" >> "$GITHUB_PATH"
[ -n "${GITHUB_ENV:-}" ] && echo "PATH=$BINDIR:$PATH" >> "$GITHUB_ENV"
export PATH="$BINDIR:$PATH"
node -v
else
echo "Install Node failed: $BINDIR/node missing" >&2
exit 1
fi
- name: Setup Yarn
run: |
corepack enable
corepack prepare yarn@${{ inputs.yarn_version }} --activate
echo "node -v: $(node -v); yarn -v: $(yarn -v)"
- name: Install
run: yarn install --frozen-lockfile
- name: Prettier check
run: yarn format:check
- name: ESLint
run: yarn lint
- name: Build
run: yarn build
- name: Install OpenSSH client
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master')
run: |
set -e
export DEBIAN_FRONTEND=noninteractive
shopt -s nullglob
for f in /etc/apt/sources.list /etc/apt/sources.list.d/debian.sources /etc/apt/sources.list.d/*.sources /etc/apt/sources.list.d/*.list; do
[ -f "$f" ] || continue
sed -i \
-e 's/deb.debian.org/mirrors.aliyun.com/g' \
-e 's/security.debian.org/mirrors.aliyun.com/g' \
"$f"
done
apt-get -o Acquire::http::Timeout=30 -o Acquire::https::Timeout=30 -o Acquire::Retries=2 update
apt-get install -y --no-install-recommends openssh-client
- name: Deploy to Nginx (tar over SSH)
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master')
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
PROJECT_DIR: ${{ inputs.project_dir }}
run: |
set -e
: "${DEPLOY_PATH:?DEPLOY_PATH (vars) is not set}"
: "${DEPLOY_HOST:?DEPLOY_HOST (vars) is not set}"
: "${DEPLOY_USER:?DEPLOY_USER (vars) is not set}"
: "${PROJECT_DIR:?project_dir is not set}"
REMOTE_ROOT="${DEPLOY_PATH}/${PROJECT_DIR}"
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "$SSH_PRIVATE_KEY" | tr -d '\r' > ~/.ssh/id_deploy
chmod 600 ~/.ssh/id_deploy
ssh-keyscan -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts
SSH=(ssh -i ~/.ssh/id_deploy -o IdentitiesOnly=yes -o StrictHostKeyChecking=yes)
"${SSH[@]}" "${DEPLOY_USER}@${DEPLOY_HOST}" "mkdir -p '${REMOTE_ROOT}' && find '${REMOTE_ROOT}' -mindepth 1 -delete"
tar czf - -C dist . | "${SSH[@]}" "${DEPLOY_USER}@${DEPLOY_HOST}" "tar xzf - -C '${REMOTE_ROOT}'"