From 357b3aa65d7f4c6c965dc232adc21c19e33d8b13 Mon Sep 17 00:00:00 2001 From: imengying Date: Fri, 4 Sep 2026 23:54:21 +0800 Subject: [PATCH] =?UTF-8?q?=E7=B2=BE=E7=AE=80=20Release=20=E4=BA=A7?= =?UTF-8?q?=E7=89=A9=E5=B9=B6=E4=BD=BF=E7=94=A8=E5=86=85=E7=BD=AE=E6=91=98?= =?UTF-8?q?=E8=A6=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/release.yml | 13 +++++----- README.md | 12 ++++----- install.ps1 | 22 ++++++++++------ install.sh | 49 ++++++++++++++++++++++++++++++----- 4 files changed, 69 insertions(+), 27 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e546e64..b2693e1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -761,16 +761,13 @@ jobs: tar -czf "release/$ASSET" -C package . tar -tzf "release/$ASSET" >/dev/null fi - (cd release && sha256sum "$ASSET" > "$ASSET.sha256") - uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4 with: subject-path: release/${{ matrix.asset }} - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: server-bundle-${{ matrix.binary }} - path: | - release/${{ matrix.asset }} - release/${{ matrix.asset }}.sha256 + path: release/${{ matrix.asset }} if-no-files-found: error release: @@ -804,10 +801,14 @@ jobs: printf '\n' >> CHANGELOG.md - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: + pattern: agent-* + path: release-assets + merge-multiple: true + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + pattern: server-bundle-* path: release-assets merge-multiple: true - - name: Include installer - run: cp install.sh install.ps1 release-assets/ - uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.3 with: body_path: CHANGELOG.md diff --git a/README.md b/README.md index d2c3bc6..22a421b 100644 --- a/README.md +++ b/README.md @@ -11,19 +11,19 @@ NodeFlare 是一个自部署的服务器监控面板,支持 SQLite、PostgreSQ Linux 或 macOS: ```bash -curl -fsSL https://github.com/imengying/NodeFlare/releases/latest/download/install.sh | sudo sh +curl -fsSL https://raw.githubusercontent.com/imengying/NodeFlare/main/install.sh | sudo sh ``` FreeBSD: ```sh -fetch -qo - https://github.com/imengying/NodeFlare/releases/latest/download/install.sh | sudo sh +fetch -qo - https://raw.githubusercontent.com/imengying/NodeFlare/main/install.sh | sudo sh ``` Windows PowerShell(管理员): ```powershell -Invoke-WebRequest https://github.com/imengying/NodeFlare/releases/latest/download/install.ps1 -OutFile "$env:TEMP\nodeflare-install.ps1" +Invoke-WebRequest https://raw.githubusercontent.com/imengying/NodeFlare/main/install.ps1 -OutFile "$env:TEMP\nodeflare-install.ps1" Unblock-File "$env:TEMP\nodeflare-install.ps1" & "$env:TEMP\nodeflare-install.ps1" ``` @@ -53,19 +53,19 @@ journalctl -u nodeflare -f 重新执行安装命令即可更新。Linux 和 macOS 卸载时默认保留配置和数据库: ```bash -curl -fsSL https://github.com/imengying/NodeFlare/releases/latest/download/install.sh | sudo sh -s -- --uninstall +curl -fsSL https://raw.githubusercontent.com/imengying/NodeFlare/main/install.sh | sudo sh -s -- --uninstall ``` 同时删除配置和数据: ```bash -curl -fsSL https://github.com/imengying/NodeFlare/releases/latest/download/install.sh | sudo sh -s -- --uninstall --purge +curl -fsSL https://raw.githubusercontent.com/imengying/NodeFlare/main/install.sh | sudo sh -s -- --uninstall --purge ``` FreeBSD: ```sh -fetch -qo - https://github.com/imengying/NodeFlare/releases/latest/download/install.sh | sudo sh -s -- --uninstall +fetch -qo - https://raw.githubusercontent.com/imengying/NodeFlare/main/install.sh | sudo sh -s -- --uninstall ``` 彻底删除时在末尾添加 `--purge`。 diff --git a/install.ps1 b/install.ps1 index 300649b..bd6618b 100644 --- a/install.ps1 +++ b/install.ps1 @@ -102,21 +102,24 @@ if ($NativeArchitecture -ne "AMD64") { } $Asset = "nodeflare-server-windows-x64.zip" -$ReleaseBase = "https://github.com/$Repository/releases/latest/download" +$ReleaseApi = "https://api.github.com/repos/$Repository/releases/latest" $TemporaryDir = Join-Path $env:TEMP "nodeflare-install-$PID" $Archive = Join-Path $TemporaryDir $Asset -$Checksum = "$Archive.sha256" $PackageDir = Join-Path $TemporaryDir "package" try { New-Item -ItemType Directory -Path $TemporaryDir -Force | Out-Null - Write-Step "下载 latest Release(Windows x64)" - Invoke-WebRequest -UseBasicParsing -Uri "$ReleaseBase/$Asset" -OutFile $Archive -TimeoutSec 120 - Invoke-WebRequest -UseBasicParsing -Uri "$ReleaseBase/$Asset.sha256" -OutFile $Checksum -TimeoutSec 30 - $Expected = ((Get-Content -LiteralPath $Checksum -Raw).Trim() -split '\s+')[0] - if ($Expected -notmatch '^[0-9a-fA-F]{64}$') { - Stop-Install "Release 校验文件无效" + Write-Step "获取 latest Release(Windows x64)" + $Release = Invoke-RestMethod -Uri $ReleaseApi -Headers @{ Accept = "application/vnd.github+json"; "User-Agent" = "nodeflare-installer" } -TimeoutSec 30 + $ReleaseAsset = $Release.assets | Where-Object { $_.name -eq $Asset } | Select-Object -First 1 + if ($Release.tag_name -notmatch '^v[0-9]+\.[0-9]+\.[0-9]+$' -or $null -eq $ReleaseAsset) { + Stop-Install "GitHub 最新 Release 无效,或缺少 $Asset" } + $DigestMatch = [regex]::Match([string]$ReleaseAsset.digest, '^sha256:([0-9a-fA-F]{64})$') + if (-not $DigestMatch.Success) { Stop-Install "Release 缺少 $Asset 的 SHA-256 摘要" } + $Expected = $DigestMatch.Groups[1].Value + Write-Step "下载 NodeFlare $($Release.tag_name)(Windows x64)" + Invoke-WebRequest -UseBasicParsing -Uri $ReleaseAsset.browser_download_url -OutFile $Archive -TimeoutSec 120 $Actual = (Get-FileHash -LiteralPath $Archive -Algorithm SHA256).Hash if ($Actual -ne $Expected) { Stop-Install "Release SHA-256 校验失败" @@ -142,6 +145,9 @@ try { if ($Version -notmatch '^\d+\.\d+\.\d+$') { Stop-Install "服务端返回了无效版本号" } + if ($Version -ne $Release.tag_name.Substring(1)) { + Stop-Install "Release $($Release.tag_name) 与服务端版本 $Version 不一致" + } $NewConfig = -not (Test-Path -LiteralPath $ConfigFile) if ($NewConfig) { diff --git a/install.sh b/install.sh index b8a89b2..1ea4e6f 100755 --- a/install.sh +++ b/install.sh @@ -237,10 +237,20 @@ download_file() { fi } +download_stdout() { + url=$1 + if command -v curl >/dev/null 2>&1; then + curl --proto '=https' --proto-redir '=https' --tlsv1.2 \ + --fail --location --silent --show-error --max-time 30 \ + -H 'Accept: application/vnd.github+json' \ + -H 'User-Agent: nodeflare-installer' \ + "$url" + else + fetch -q -T 30 -o - "$url" + fi +} + verify_checksum() { - expected=$(sed -n '1{s/[[:space:]].*//;p;q;}' "$checksum" | tr '[:upper:]' '[:lower:]') - [ "${#expected}" -eq 64 ] || fail "Release 校验文件无效" - case "$expected" in *[!0-9a-f]*) fail "Release 校验文件无效" ;; esac case "$platform" in linux) actual=$(sha256sum "$archive" | sed 's/[[:space:]].*//') ;; macos) actual=$(shasum -a 256 "$archive" | sed 's/[[:space:]].*//') ;; @@ -281,11 +291,34 @@ download_release() { download_dir=$(mktemp -d "${TMPDIR:-/tmp}/nodeflare-install.XXXXXX") archive=$download_dir/$asset - checksum=$download_dir/$asset.sha256 - release_base="https://github.com/$repository/releases/latest/download" - log "下载 latest Release ($release_label)" + release_api="https://api.github.com/repos/$repository/releases/latest" + log "获取 latest Release ($release_label)" + release_json=$(download_stdout "$release_api") + release_tag=$(printf '%s\n' "$release_json" | tr ',' '\n' | sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' | sed -n '1p') + printf '%s\n' "$release_tag" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+$' \ + || fail "GitHub 最新 Release 标签无效" + expected=$(printf '%s\n' "$release_json" | tr '{' '\n' | awk -v name="$asset" ' + { + compact = $0 + gsub(/[[:space:]]/, "", compact) + if (index(compact, "\"name\":\"" name "\"") > 0) selected = 1 + else if (index(compact, "\"name\":") > 0) selected = 0 + } + selected { + marker = "\"digest\":\"sha256:" + position = index(compact, marker) + if (position == 0) next + digest = substr(compact, position + length(marker), 64) + if (length(digest) == 64 && digest !~ /[^0-9a-fA-F]/) { + print tolower(digest) + exit + } + } + ') + [ -n "$expected" ] || fail "Release 缺少 $asset 的 SHA-256 摘要" + release_base="https://github.com/$repository/releases/download/$release_tag" + log "下载 NodeFlare $release_tag ($release_label)" download_file "$release_base/$asset" "$archive" 120 - download_file "$release_base/$asset.sha256" "$checksum" 30 verify_checksum package_dir=$download_dir/package @@ -301,6 +334,8 @@ download_release() { release_version=${binary_version##* } printf '%s\n' "$release_version" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$' \ || fail "服务端返回了无效版本号" + [ "$release_version" = "${release_tag#v}" ] \ + || fail "Release $release_tag 与服务端版本 $release_version 不一致" } write_openrc_service() {