diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index d4edf24..d075af9 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -7,14 +7,22 @@ on: jobs: release-linux-x86_64: - runs-on: runner_admin + runs-on: ubuntu-latest steps: - name: 检出代码 env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} + GIT_TERMINAL_PROMPT: "0" run: | set -eux + SERVER_URL="${GITHUB_SERVER_URL:-${GITEA_SERVER_URL:-https://gitea.kmux.cn}}" + REPOSITORY="${GITHUB_REPOSITORY:-${GITEA_REPOSITORY:-}}" TAG="${GITHUB_REF_NAME:-${GITEA_REF_NAME:-}}" + if [ -z "$REPOSITORY" ]; then + echo "无法识别触发仓库" + env | sort + exit 1 + fi if [ -z "$TAG" ] && [ -n "${GITHUB_REF:-}" ]; then TAG="${GITHUB_REF##*/}" fi @@ -23,16 +31,17 @@ jobs: env | sort exit 1 fi + CLONE_URL="${SERVER_URL%/}/${REPOSITORY}.git" printf '%s' "$TAG" > /tmp/lightops-release-tag rm -rf lightops-src if [ -n "${GITEA_TOKEN:-}" ]; then - git clone "https://oauth2:${GITEA_TOKEN}@gitea.kmux.cn/Eeveid/lightOps.git" lightops-src + AUTH_HEADER="Authorization: Basic $(printf 'oauth2:%s' "$GITEA_TOKEN" | base64 | tr -d '\n')" + git -c http.extraHeader="$AUTH_HEADER" clone --branch "$TAG" --depth 1 --single-branch "$CLONE_URL" lightops-src else - git clone https://gitea.kmux.cn/Eeveid/lightOps.git lightops-src + git clone --branch "$TAG" --depth 1 --single-branch "$CLONE_URL" lightops-src fi cd lightops-src - git fetch --tags --force - git checkout "$TAG" + git rev-parse --verify HEAD - name: 安装系统依赖 run: | @@ -49,39 +58,73 @@ jobs: fi - name: 安装 Rust + env: + RUSTUP_DIST_SERVER: https://rsproxy.cn + RUSTUP_UPDATE_ROOT: https://rsproxy.cn/rustup run: | set -eux - if ! command -v cargo >/dev/null 2>&1; then + if ! command -v rustup >/dev/null 2>&1; then curl --proto '=https' --tlsv1.2 -fsSL https://sh.rustup.rs | sh -s -- -y --profile minimal - . "$HOME/.cargo/env" fi + . "$HOME/.cargo/env" + rustup toolchain install stable --profile minimal --no-self-update + rustup default stable + HOST_TARGET="$(rustc -vV | sed -n 's/^host: //p')" + BUILD_TARGET="$HOST_TARGET" + if [ "$HOST_TARGET" != "x86_64-unknown-linux-gnu" ] && command -v rustup >/dev/null 2>&1; then + if rustup target list --installed | grep -qx 'x86_64-unknown-linux-gnu' && command -v x86_64-linux-gnu-gcc >/dev/null 2>&1; then + BUILD_TARGET="x86_64-unknown-linux-gnu" + fi + fi + printf '%s' "$BUILD_TARGET" > /tmp/lightops-build-target + echo "使用 Rust 构建目标: $BUILD_TARGET" rustc -V cargo -V + mkdir -p "$HOME/.cargo" + printf '%s\n' \ + '[source.crates-io]' \ + 'replace-with = "rsproxy-sparse"' \ + '' \ + '[source.rsproxy-sparse]' \ + 'registry = "sparse+https://rsproxy.cn/index/"' \ + >"$HOME/.cargo/config.toml" - name: 构建发布包 + env: + RUSTUP_DIST_SERVER: https://rsproxy.cn + RUSTUP_UPDATE_ROOT: https://rsproxy.cn/rustup run: | set -eux - . "$HOME/.cargo/env" 2>/dev/null || true + . "$HOME/.cargo/env" cd lightops-src TAG="$(cat /tmp/lightops-release-tag)" VERSION="${TAG#v}" - bash scripts/build-release.sh --version "$VERSION" --target x86_64-unknown-linux-gnu + BUILD_TARGET="$(cat /tmp/lightops-build-target 2>/dev/null || true)" + if [ -z "$BUILD_TARGET" ]; then + BUILD_TARGET="$(rustc -vV | sed -n 's/^host: //p')" + fi + echo "构建发布目标: $BUILD_TARGET" + bash scripts/build-release.sh --version "$VERSION" --target "$BUILD_TARGET" - name: 发布到 Gitea Release env: - GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} - GITEA_URL: https://gitea.kmux.cn - GITEA_OWNER: Eeveid - GITEA_REPO: lightOps + GITEA_TOKEN: ${{ secrets.RELEASE_TOKEN }} run: | set -eux + SERVER_URL="${GITHUB_SERVER_URL:-${GITEA_SERVER_URL:-https://gitea.kmux.cn}}" + REPOSITORY="${GITHUB_REPOSITORY:-${GITEA_REPOSITORY:-}}" + GITEA_URL="${SERVER_URL%/}" + GITEA_OWNER="${REPOSITORY%%/*}" + GITEA_REPO="${REPOSITORY#*/}" cd lightops-src TAG="$(cat /tmp/lightops-release-tag)" - TARGET_SHA="$(git rev-parse HEAD)" bash scripts/publish-gitea-release.sh \ + --gitea-url "$GITEA_URL" \ + --owner "$GITEA_OWNER" \ + --repo "$GITEA_REPO" \ --tag "$TAG" \ --title "LightOps ${TAG}" \ - --target "$TARGET_SHA" \ + --target "main" \ --no-create-tag \ --no-push-tag \ --package target/releases/*.tar.gz \ diff --git a/scripts/build-release.sh b/scripts/build-release.sh index 8f546be..a52f858 100755 --- a/scripts/build-release.sh +++ b/scripts/build-release.sh @@ -111,6 +111,11 @@ PLATFORM="${TARGET:-$(detect_platform)}" PACKAGE_NAME="lightops-${VERSION}-${PLATFORM}" STAGE_DIR="target/release-package/${PACKAGE_NAME}" ARCHIVE_PATH="${OUTPUT_DIR}/${PACKAGE_NAME}.tar.gz" +HOST_TARGET="$(rustc -vV 2>/dev/null | sed -n 's/^host: //p')" +NATIVE_TARGET="false" +if [[ -n "$TARGET" && -n "$HOST_TARGET" && "$TARGET" == "$HOST_TARGET" ]]; then + NATIVE_TARGET="true" +fi if [[ "$SKIP_BUILD" != "true" ]]; then log "构建前端" @@ -124,7 +129,7 @@ if [[ "$SKIP_BUILD" != "true" ]]; then log "构建 Rust 二进制" cd "$ROOT" - if [[ -n "$TARGET" ]]; then + if [[ -n "$TARGET" && "$NATIVE_TARGET" != "true" ]]; then cargo build --release --target "$TARGET" -p lightops-server -p lightops-agent BIN_DIR="target/${TARGET}/release" else @@ -133,7 +138,7 @@ if [[ "$SKIP_BUILD" != "true" ]]; then fi else cd "$ROOT" - if [[ -n "$TARGET" ]]; then + if [[ -n "$TARGET" && "$NATIVE_TARGET" != "true" ]]; then BIN_DIR="target/${TARGET}/release" else BIN_DIR="target/release" diff --git a/scripts/publish-gitea-release.sh b/scripts/publish-gitea-release.sh index fde3288..8dbe11a 100755 --- a/scripts/publish-gitea-release.sh +++ b/scripts/publish-gitea-release.sh @@ -110,8 +110,27 @@ require_cmd() { command -v "$1" >/dev/null 2>&1 || fail "缺少命令:$1" } +detect_json_runtime() { + if command -v node >/dev/null 2>&1; then + echo "node" + elif command -v python3 >/dev/null 2>&1; then + echo "python3" + elif command -v python >/dev/null 2>&1; then + echo "python" + else + return 1 + fi +} + json_escape() { - python -c 'import json,sys; print(json.dumps(sys.stdin.read()))' + case "$JSON_RUNTIME" in + node) + node -e 'let s=""; process.stdin.setEncoding("utf8"); process.stdin.on("data", d => s += d); process.stdin.on("end", () => process.stdout.write(JSON.stringify(s)));' + ;; + *) + "$JSON_RUNTIME" -c 'import json,sys; print(json.dumps(sys.stdin.read()))' + ;; + esac } api_url() { @@ -130,8 +149,32 @@ api_post_json() { "$1" } +api_post_json_with_status() { + local output_file status + output_file="$(mktemp)" + status="$(curl -sS -o "$output_file" -w '%{http_code}' -X POST \ + -H "Authorization: token ${GITEA_TOKEN}" \ + -H "Content-Type: application/json" \ + -d "$2" \ + "$1")" || { + cat "$output_file" >&2 || true + rm -f "$output_file" + return 1 + } + cat "$output_file" + rm -f "$output_file" + printf '\n%s' "$status" +} + release_id_from_json() { - python -c 'import json,sys; print(json.load(sys.stdin)["id"])' + case "$JSON_RUNTIME" in + node) + node -e 'let s=""; process.stdin.setEncoding("utf8"); process.stdin.on("data", d => s += d); process.stdin.on("end", () => process.stdout.write(String(JSON.parse(s).id)));' + ;; + *) + "$JSON_RUNTIME" -c 'import json,sys; print(json.load(sys.stdin)["id"])' + ;; + esac } [[ -n "$TAG" ]] || fail "必须指定 --tag" @@ -141,7 +184,7 @@ release_id_from_json() { require_cmd curl require_cmd git -require_cmd python +JSON_RUNTIME="$(detect_json_runtime)" || fail "缺少命令:node、python 或 python3" for package in "${PACKAGES[@]}"; do [[ -f "$package" ]] || fail "发布包不存在:$package" @@ -159,14 +202,18 @@ fi release_url="$(api_url "releases/tags/${TAG}")" release_json="" -if release_json="$(api_get "$release_url" 2>/dev/null)"; then +release_status="$(curl -sS -o /dev/null -w '%{http_code}' -H "Authorization: token ${GITEA_TOKEN}" "$release_url" || true)" +if [[ "$release_status" == "200" ]] && release_json="$(api_get "$release_url" 2>/dev/null)"; then log "Release 已存在:$TAG" else log "创建 Release:$TAG" title_json="$(printf '%s' "$TITLE" | json_escape)" notes_json="$(printf '%s' "$NOTES" | json_escape)" payload="{\"tag_name\":\"${TAG}\",\"target_commitish\":\"${TARGET}\",\"name\":${title_json},\"body\":${notes_json},\"draft\":false,\"prerelease\":${PRERELEASE}}" - release_json="$(api_post_json "$(api_url releases)" "$payload")" + create_result="$(api_post_json_with_status "$(api_url releases)" "$payload")" || fail "创建 Release 请求失败" + create_status="${create_result##*$'\n'}" + release_json="${create_result%$'\n'*}" + [[ "$create_status" == "201" || "$create_status" == "200" ]] || fail "创建 Release 失败,HTTP 状态码:$create_status" fi release_id="$(printf '%s' "$release_json" | release_id_from_json)"