Skip to content

feat: 更新版本号至 v1.11.1,新增特殊音频替换逻辑以支持特定事件的音效替换 #68

feat: 更新版本号至 v1.11.1,新增特殊音频替换逻辑以支持特定事件的音效替换

feat: 更新版本号至 v1.11.1,新增特殊音频替换逻辑以支持特定事件的音效替换 #68

Workflow file for this run

name: Release
on:
push:
tags:
- '*.*.*'
- '*.*.*-*'
jobs:
build-and-release:
runs-on: windows-latest
permissions:
contents: write
packages: read
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.x'
- name: Configure NuGet authentication
run: dotnet nuget update source Duckov-Custom-Model --username Duckov-Custom-Model --password ${{ secrets.GITHUB_TOKEN }} --store-password-in-clear-text
- name: Restore dependencies
run: dotnet restore
env:
CI: true
GITHUB_ACTIONS: true
- name: Build
run: dotnet build --configuration Release --no-restore
env:
CI: true
GITHUB_ACTIONS: true
- name: Create Release Package
run: |
$outputPath = "DuckovCustomModel/bin/Release/netstandard2.1"
$packageDir = "DuckovCustomModel/bin/Release/PackageTemp"
$zipPath = "DuckovCustomModel/bin/Release/DuckovCustomModel.zip"
New-Item -ItemType Directory -Path $packageDir -Force | Out-Null
Get-ChildItem -Path $outputPath -Recurse -File | ForEach-Object {
$relativePath = $_.FullName.Substring((Resolve-Path $outputPath).Path.Length).TrimStart('\', '/')
$destPath = Join-Path $packageDir $relativePath
$destDir = Split-Path $destPath -Parent
if (-not (Test-Path $destDir)) {
New-Item -ItemType Directory -Path $destDir -Force | Out-Null
}
Copy-Item $_.FullName -Destination $destPath -Force
}
if (Test-Path $zipPath) {
Remove-Item $zipPath -Force
}
Compress-Archive -Path (Join-Path $packageDir '*') -DestinationPath $zipPath -Force
Remove-Item -Path $packageDir -Recurse -Force
shell: pwsh
- name: Upload Release Artifacts
uses: actions/upload-artifact@v4
with:
name: release-package
path: DuckovCustomModel/bin/Release/DuckovCustomModel.zip
retention-days: 30
- name: Prepare Release Body
id: prepare_release_body
run: |
$tagName = "${{ github.ref_name }}"
$version = $tagName -replace '^v', ''
$changelogFile = "CHANGELOG.md"
$manualChangelog = ""
if (Test-Path $changelogFile) {
$content = Get-Content $changelogFile -Raw -Encoding UTF8
$escapedVersion = [regex]::Escape($version)
# 判断是否为 fix 版本
$isFixVersion = $version -match '-fix\d+$'
if ($isFixVersion) {
# Fix 版本:提取从 fix 版本到下一个版本之间的所有内容
# 例如:v1.9.5-fix1 应该包含 v1.9.5-fix1 和 v1.9.5 的内容
# 提取基础版本号(去掉 -fix1 等后缀)
$baseVersion = $version -replace '-fix\d+$', ''
$escapedBaseVersion = [regex]::Escape($baseVersion)
# 找到 fix 版本的起始位置
$fixVersionPattern = "##\s+v?$escapedVersion\s*\r?\n"
$fixVersionMatch = [regex]::Match($content, $fixVersionPattern)
if ($fixVersionMatch.Success) {
# 从 fix 版本开始,找到下一个不同版本号的位置
# 需要跳过基础版本号(如 v1.9.5),找到下一个不同的版本号(如 v1.9.4)
$startPos = $fixVersionMatch.Index + $fixVersionMatch.Length
$remainingContent = $content.Substring($startPos)
# 先匹配所有版本号标题
$allVersionPattern = "(?m)^##\s+v?(\d+\.\d+\.\d+(?:-fix\d+)?)"
$allVersionMatches = [regex]::Matches($remainingContent, $allVersionPattern)
$nextVersionIndex = -1
foreach ($match in $allVersionMatches) {
$matchedVersion = $match.Groups[1].Value
# 如果匹配到的版本号不是基础版本号的任何变体,则找到了下一个不同版本号
if ($matchedVersion -notmatch "^$escapedBaseVersion(?:-fix\d+)?$") {
$nextVersionIndex = $match.Index
break
}
}
if ($nextVersionIndex -ge 0) {
# 提取到下一个不同版本号之前的所有内容
$changelogContent = $remainingContent.Substring(0, $nextVersionIndex)
} else {
# 如果没有找到下一个不同版本号,提取到文件结尾
$changelogContent = $remainingContent
}
# 分离 fix 内容和基础版本内容
$baseVersionPattern = "##\s+v?$escapedBaseVersion\s*\r?\n"
$baseVersionMatch = [regex]::Match($changelogContent, $baseVersionPattern)
if ($baseVersionMatch.Success) {
# 分离两部分内容
$fixContent = $changelogContent.Substring(0, $baseVersionMatch.Index).Trim()
$baseContent = $changelogContent.Substring($baseVersionMatch.Index + $baseVersionMatch.Length).Trim()
# 处理 fix 内容:保留 fix 版本标识,但转换为更清晰的格式
# 获取当前 fix 版本号
$currentFixNumber = ""
$fixMatch = [regex]::Match($version, '-fix(\d+)$')
if ($fixMatch.Success) {
$currentFixNumber = $fixMatch.Groups[1].Value
}
# 匹配所有 fix 版本标题行,转换为只带 fix 编号的格式(但当前 fix 版本不添加标题)
$fixContent = [regex]::Replace($fixContent, "(?m)^##\s+v?$escapedBaseVersion-fix(\d+)\s*\r?\n", {
param($match)
$matchedFixNumber = $match.Groups[1].Value
if ($matchedFixNumber -eq $currentFixNumber) {
# 当前 fix 版本,不添加标题,只保留换行
return "`n`n"
} else {
# 其他 fix 版本,添加标题
return "`n`n**fix$matchedFixNumber 修复:**`n`n"
}
})
# 如果当前 fix 版本内容在开头且没有标题,保持原样(不添加标题)
# 清理多余的连续换行(超过2个换行的地方只保留2个)
$fixContent = [regex]::Replace($fixContent, "(\r?\n){3,}", "`n`n")
# 移除基础版本标题行(如果存在)
$baseContent = [regex]::Replace($baseContent, "(?m)^##\s+v?$escapedBaseVersion(?:-fix\d+)?\s*\r?\n", "")
# 清理基础版本内容的连续换行
$baseContent = [regex]::Replace($baseContent, "(\r?\n){3,}", "`n`n")
# 组合两部分,明确区分 fix 内容和原始版本内容
if ($fixContent -and $baseContent) {
$manualChangelog = "**修复内容:**`n`n$fixContent`n`n**原始更新内容:**`n`n$baseContent"
} elseif ($fixContent) {
$manualChangelog = "**修复内容:**`n`n$fixContent"
} else {
$manualChangelog = $baseContent
}
} else {
# 如果没有找到基础版本,获取当前 fix 版本号
$currentFixNumber = ""
$fixMatch = [regex]::Match($version, '-fix(\d+)$')
if ($fixMatch.Success) {
$currentFixNumber = $fixMatch.Groups[1].Value
}
# 转换 fix 版本标题行(当前 fix 版本不添加标题)
$changelogContent = [regex]::Replace($changelogContent, "(?m)^##\s+v?$escapedBaseVersion-fix(\d+)\s*\r?\n", {
param($match)
$matchedFixNumber = $match.Groups[1].Value
if ($matchedFixNumber -eq $currentFixNumber) {
# 当前 fix 版本,不添加标题,只保留换行
return "`n`n"
} else {
# 其他 fix 版本,添加标题
return "`n`n**fix$matchedFixNumber 修复:**`n`n"
}
})
# 清理多余的连续换行
$changelogContent = [regex]::Replace($changelogContent, "(\r?\n){3,}", "`n`n")
$manualChangelog = $changelogContent.Trim()
}
Write-Host "✓ 从 CHANGELOG.md 提取到 fix 版本 changelog ($($manualChangelog.Length) 字符)"
if ($manualChangelog.Length -gt 0) {
Write-Host "预览前100字符: $($manualChangelog.Substring(0, [Math]::Min(100, $manualChangelog.Length)))"
}
} else {
Write-Host "⚠ 未在 CHANGELOG.md 中找到 fix 版本 $version 的内容"
}
} else {
# 非 fix 版本:使用原有逻辑
$pattern = "(?s)##\s+v?$escapedVersion\s*\r?\n(.*?)(?=\r?\n##\s+v?\d+\.\d+\.\d+|$)"
$match = [regex]::Match($content, $pattern)
if ($match.Success) {
$manualChangelog = $match.Groups[1].Value.Trim()
Write-Host "✓ 从 CHANGELOG.md 提取到 changelog ($($manualChangelog.Length) 字符)"
if ($manualChangelog.Length -gt 0) {
Write-Host "预览前100字符: $($manualChangelog.Substring(0, [Math]::Min(100, $manualChangelog.Length)))"
}
} else {
Write-Host "⚠ 未在 CHANGELOG.md 中找到版本 $version 的内容"
Write-Host "尝试的正则表达式: $pattern"
}
}
}
$headers = @{
Authorization = "token ${{ secrets.GITHUB_TOKEN }}"
Accept = "application/vnd.github.v3+json"
}
$generateNotesUrl = "https://api.github.com/repos/${{ github.repository }}/releases/generate-notes"
$generateNotesBody = @{
tag_name = $tagName
} | ConvertTo-Json
$autoNotes = ""
try {
$notesResponse = Invoke-RestMethod -Uri $generateNotesUrl -Method Post -Headers $headers -Body $generateNotesBody -ContentType "application/json"
$autoNotes = $notesResponse.body
Write-Host "✓ 获取到自动生成的 release notes"
} catch {
Write-Host "⚠ 无法获取自动生成的 release notes: $_"
}
$releaseBody = ""
if ($manualChangelog) {
$releaseBody = $manualChangelog
if ($autoNotes) {
$releaseBody += "`n`n---`n`n"
}
}
if ($autoNotes) {
$releaseBody += $autoNotes
}
if (-not $releaseBody) {
$releaseBody = "Release $tagName"
}
echo "release_body<<EOF" >> $env:GITHUB_OUTPUT
echo "$releaseBody" >> $env:GITHUB_OUTPUT
echo "EOF" >> $env:GITHUB_OUTPUT
Write-Host "✓ Release body 准备完成 ($($releaseBody.Length) 字符)"
shell: pwsh
- name: Create GitHub Release
id: create_release
uses: softprops/action-gh-release@v1
with:
files: DuckovCustomModel/bin/Release/DuckovCustomModel.zip
body: ${{ steps.prepare_release_body.outputs.release_body }}
generate_release_notes: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Check Steam Workshop Secrets
id: check_steam_secrets
run: |
$hasUsername = "${{ secrets.STEAM_USERNAME }}" -ne ""
$hasPassword = "${{ secrets.STEAM_PASSWORD }}" -ne ""
$hasAppId = "${{ secrets.STEAM_APP_ID }}" -ne ""
if ($hasUsername -and $hasPassword -and $hasAppId) {
echo "steam_enabled=true" >> $env:GITHUB_OUTPUT
Write-Host "✓ Steam Workshop secrets 已配置"
} else {
echo "steam_enabled=false" >> $env:GITHUB_OUTPUT
Write-Host "⚠ Steam Workshop secrets 未配置,将跳过上传"
}
shell: pwsh
- name: Setup SteamCMD
if: steps.check_steam_secrets.outputs.steam_enabled == 'true'
uses: buildalon/setup-steamcmd@v1
- name: Prepare Workshop Content
if: steps.check_steam_secrets.outputs.steam_enabled == 'true'
id: prepare_workshop
run: |
$outputPath = "DuckovCustomModel/bin/Release/netstandard2.1"
$workshopDir = "DuckovCustomModel/bin/Release/WorkshopContent"
# 检查编译输出目录是否存在
if (-not (Test-Path $outputPath)) {
Write-Error "编译输出目录不存在: $outputPath,请确保 Build 步骤已成功执行"
exit 1
}
# 创建 Workshop 内容目录
if (Test-Path $workshopDir) {
Remove-Item -Path $workshopDir -Recurse -Force
}
New-Item -ItemType Directory -Path $workshopDir -Force | Out-Null
# 从编译输出目录复制所有文件到 Workshop 目录
Get-ChildItem -Path $outputPath -Recurse -File | ForEach-Object {
$relativePath = $_.FullName.Substring((Resolve-Path $outputPath).Path.Length).TrimStart('\', '/')
$destPath = Join-Path $workshopDir $relativePath
$destDir = Split-Path $destPath -Parent
if (-not (Test-Path $destDir)) {
New-Item -ItemType Directory -Path $destDir -Force | Out-Null
}
Copy-Item $_.FullName -Destination $destPath -Force
}
Write-Host "✓ Workshop 内容已准备完成(从 $outputPath 复制)"
echo "workshop_dir=$workshopDir" >> $env:GITHUB_OUTPUT
shell: pwsh
- name: Upload to Steam Workshop
if: steps.check_steam_secrets.outputs.steam_enabled == 'true'
id: upload_steam
uses: buildalon/upload-steam@v1
with:
username: ${{ secrets.STEAM_USERNAME }}
password: ${{ secrets.STEAM_PASSWORD }}
app_id: ${{ secrets.STEAM_APP_ID }}
workshop_item_id: ${{ secrets.STEAM_WORKSHOP_ITEM_ID }}
description: ${{ steps.prepare_release_body.outputs.release_body }}
content_root: ${{ steps.prepare_workshop.outputs.workshop_dir }}
- name: Get Release Info
id: release_info
if: success()
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REPOSITORY: ${{ github.repository }}
TAG_NAME: ${{ github.ref_name }}
run: |
$scriptContent = @'
# -*- coding: utf-8 -*-
import json
import os
import sys
import time
import urllib.request
from datetime import datetime
# Fix encoding for Windows console
if sys.platform == 'win32':
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')
def get_release_with_retry(api_url, headers, package_file_name="DuckovCustomModel.zip", max_retries=15, retry_delay=3):
last_error = None
release = None
for attempt in range(1, max_retries + 1):
try:
print(f"尝试获取 Release 信息 ({attempt}/{max_retries})...")
req = urllib.request.Request(api_url, headers=headers)
with urllib.request.urlopen(req) as response:
release = json.load(response)
if not release.get('tag_name'):
raise ValueError("Release 数据不完整:缺少 tag_name")
assets = release.get('assets', [])
package_asset = next((a for a in assets if a.get('name') == package_file_name), None)
if package_asset:
print("✓ Release 信息获取成功,assets 已上传")
print(f" 找到打包文件: {package_asset.get('name')}")
print(f" 下载链接: {package_asset.get('browser_download_url')}")
return release
if attempt < max_retries:
print(f"⚠ Assets 尚未上传完成,等待 {retry_delay} 秒后重试...")
time.sleep(retry_delay)
else:
print("⚠ 已达到最大重试次数,assets 可能尚未上传完成")
return release
except urllib.error.HTTPError as e:
last_error = e
status_code = e.code
print(f"⚠ 尝试 {attempt}/{max_retries} 失败")
print(f" HTTP 状态码: {status_code}")
print(f" 错误信息: {str(e)}")
if status_code == 404 and attempt < max_retries:
print(f"等待 {retry_delay} 秒后重试...")
time.sleep(retry_delay)
elif status_code == 403:
print("API 访问被拒绝,可能是限流或权限问题")
if attempt < max_retries:
time.sleep(retry_delay)
elif attempt >= max_retries:
raise Exception(f"获取 Release 信息失败,已重试 {max_retries} 次: {str(e)}")
except Exception as e:
last_error = e
print(f"⚠ 尝试 {attempt}/{max_retries} 失败: {str(e)}")
if attempt >= max_retries:
raise Exception(f"获取 Release 信息失败,已重试 {max_retries} 次: {str(e)}")
time.sleep(retry_delay)
if not release:
raise Exception(f"获取 Release 信息失败,已重试 {max_retries} 次: {last_error}")
return release
def format_datetime_to_iso8601(dt_value):
if isinstance(dt_value, str):
try:
for fmt in ["%Y-%m-%dT%H:%M:%SZ", "%Y-%m-%dT%H:%M:%S.%fZ", "%Y-%m-%dT%H:%M:%S%z"]:
try:
dt = datetime.strptime(dt_value.replace('Z', '+00:00'), fmt.replace('Z', '%z'))
return dt.strftime("%Y-%m-%dT%H:%M:%S.000Z")
except:
continue
dt = datetime.fromisoformat(dt_value.replace('Z', '+00:00'))
return dt.strftime("%Y-%m-%dT%H:%M:%S.000Z")
except Exception as e:
print(f"⚠ 无法解析日期格式: {dt_value},使用原始值")
return dt_value
else:
return dt_value
def parse_download_links(assets, package_file_name="DuckovCustomModel.zip"):
download_links = []
if assets:
package_asset = next((a for a in assets if a.get('name') == package_file_name), None)
if package_asset and package_asset.get('browser_download_url'):
download_links.append({
'name': 'Github Release',
'url': package_asset.get('browser_download_url')
})
return download_links
github_token = os.environ.get('GITHUB_TOKEN')
github_repository = os.environ.get('GITHUB_REPOSITORY')
tag_name = os.environ.get('TAG_NAME')
if not github_token or not github_repository or not tag_name:
print("::error::缺少必要的环境变量", file=sys.stderr)
sys.exit(1)
api_url = f"https://api.github.com/repos/{github_repository}/releases/tags/{tag_name}"
print("获取 Release 信息...")
print(f"Tag: {tag_name}")
print(f"API URL: {api_url}")
headers = {
'Authorization': f'token {github_token}',
'Accept': 'application/vnd.github.v3+json'
}
release = get_release_with_retry(api_url, headers, max_retries=15, retry_delay=3)
version = release.get('tag_name', '').lstrip('v')
release_name = release.get('name') or f"Release {version}"
published_at = format_datetime_to_iso8601(release.get('published_at', ''))
changelog = release.get('body') or ''
download_links = parse_download_links(release.get('assets', []))
print("Release 信息:")
print(f" 版本: {version}")
print(f" 名称: {release_name}")
print(f" 发布时间: {published_at}")
print(f" 更新日志: {'已设置 (' + str(len(changelog)) + ' 字符)' if changelog else '未设置'}")
print(f" 下载链接: {'已找到 (' + str(len(download_links)) + ' 项)' if download_links else '未找到'}")
output_file = os.environ.get('GITHUB_OUTPUT')
if output_file:
with open(output_file, 'a', encoding='utf-8') as f:
f.write(f"version={version}\n")
f.write(f"release_name={release_name}\n")
f.write(f"published_at={published_at}\n")
delimiter_changelog = f"CHANGELOG_EOF_{os.urandom(8).hex()}"
f.write(f"changelog<<{delimiter_changelog}\n")
f.write(changelog)
f.write(f"\n{delimiter_changelog}\n")
delimiter_download = f"DOWNLOAD_LINKS_EOF_{os.urandom(8).hex()}"
f.write(f"download_links<<{delimiter_download}\n")
f.write(json.dumps(download_links, ensure_ascii=False))
f.write(f"\n{delimiter_download}\n")
else:
print("::error::GITHUB_OUTPUT 环境变量未设置", file=sys.stderr)
sys.exit(1)
'@
$scriptPath = Join-Path $env:TEMP "get_release_info_$(New-Guid).py"
$scriptContent | Set-Content -Path $scriptPath -Encoding UTF8 -NoNewline
try {
python $scriptPath
if ($LASTEXITCODE -ne 0) {
Write-Error "Python 脚本执行失败,退出码: $LASTEXITCODE"
exit $LASTEXITCODE
}
} finally {
if (Test-Path $scriptPath) {
Remove-Item -Path $scriptPath -Force
}
}
shell: pwsh
- name: Trigger Pages Update
if: success()
env:
GITHUB_TOKEN: ${{ secrets.PAGES_REPO_TOKEN }}
PAGES_REPO_OWNER: ${{ secrets.PAGES_REPO_OWNER }}
PAGES_REPO_NAME: ${{ secrets.PAGES_REPO_NAME }}
RELEASE_VERSION: ${{ steps.release_info.outputs.version }}
RELEASE_NAME: ${{ steps.release_info.outputs.release_name }}
RELEASE_PUBLISHED_AT: ${{ steps.release_info.outputs.published_at }}
RELEASE_CHANGELOG: ${{ steps.release_info.outputs.changelog }}
RELEASE_DOWNLOAD_LINKS: ${{ steps.release_info.outputs.download_links }}
run: |
$scriptContent = @'
# -*- coding: utf-8 -*-
import json
import os
import sys
import time
import urllib.request
# Fix encoding for Windows console
if sys.platform == 'win32':
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')
def parse_download_links_from_json(json_str):
if not json_str or not json_str.strip():
return None
trimmed = json_str.strip()
if trimmed in ['[]', 'null', 'undefined', '']:
return None
try:
parsed = json.loads(trimmed)
if isinstance(parsed, list):
valid_links = []
for item in parsed:
if isinstance(item, dict) and 'name' in item and 'url' in item:
name = str(item.get('name', ''))
url = str(item.get('url', ''))
if name and url:
valid_links.append({
'name': name,
'url': url
})
return valid_links if valid_links else None
elif isinstance(parsed, dict):
if 'name' in parsed and 'url' in parsed:
name = str(parsed.get('name', ''))
url = str(parsed.get('url', ''))
if name and url:
return [{'name': name, 'url': url}]
return None
except Exception as e:
print(f"⚠ download_links JSON 解析失败: {e}", file=sys.stderr)
return None
def invoke_repository_dispatch(api_url, headers, payload, max_retries=15, retry_delay=5):
body = {
'event_type': 'update-release',
'client_payload': payload
}
body_json = json.dumps(body, ensure_ascii=False)
body_bytes = body_json.encode('utf-8')
last_error = None
for attempt in range(1, max_retries + 1):
try:
print(f"尝试触发页面更新 ({attempt}/{max_retries})...")
req = urllib.request.Request(api_url, data=body_bytes, headers=headers, method='POST')
with urllib.request.urlopen(req) as response:
status_code = response.getcode()
# GitHub API returns 204 No Content on success for repository_dispatch
if status_code == 204:
print("✓ 页面更新触发成功 (204 No Content)")
return True
# Try to read response body if available
try:
response_body = response.read().decode('utf-8')
if response_body:
response_data = json.loads(response_body)
print("✓ 页面更新触发成功")
print(f"响应: {json.dumps(response_data, ensure_ascii=False)}")
else:
print(f"✓ 页面更新触发成功 (状态码: {status_code}, 无响应体)")
return True
except json.JSONDecodeError:
# Response is not JSON, but status code indicates success
print(f"✓ 页面更新触发成功 (状态码: {status_code}, 非 JSON 响应)")
return True
except urllib.error.HTTPError as e:
last_error = e
status_code = e.code
print(f"⚠ 尝试 {attempt}/{max_retries} 失败", file=sys.stderr)
print(f" HTTP 状态码: {status_code}", file=sys.stderr)
print(f" 错误信息: {str(e)}", file=sys.stderr)
if e.fp:
try:
response_body = e.fp.read().decode('utf-8')
print(f" 响应内容: {response_body}", file=sys.stderr)
except:
print(" 无法读取响应内容", file=sys.stderr)
if attempt < max_retries:
print(f"等待 {retry_delay} 秒后重试...")
time.sleep(retry_delay)
except Exception as e:
last_error = e
print(f"⚠ 尝试 {attempt}/{max_retries} 失败: {str(e)}", file=sys.stderr)
if attempt < max_retries:
print(f"等待 {retry_delay} 秒后重试...")
time.sleep(retry_delay)
raise Exception(f"页面更新触发失败,已重试 {max_retries} 次: {last_error}")
pages_repo_owner = os.environ.get('PAGES_REPO_OWNER')
pages_repo_name = os.environ.get('PAGES_REPO_NAME')
pages_repo_token = os.environ.get('GITHUB_TOKEN')
required_secrets = {
'PAGES_REPO_OWNER': pages_repo_owner,
'PAGES_REPO_NAME': pages_repo_name,
'PAGES_REPO_TOKEN': pages_repo_token
}
for key, value in required_secrets.items():
if not value or not value.strip():
print(f"::error::{key} secret is not set", file=sys.stderr)
sys.exit(1)
client_payload = {
'version': os.environ.get('RELEASE_VERSION', ''),
'release_name': os.environ.get('RELEASE_NAME', ''),
'published_at': os.environ.get('RELEASE_PUBLISHED_AT', '')
}
changelog = os.environ.get('RELEASE_CHANGELOG', '')
if changelog:
client_payload['changelog'] = changelog
download_links = parse_download_links_from_json(os.environ.get('RELEASE_DOWNLOAD_LINKS', ''))
if download_links:
client_payload['download_links'] = download_links
headers = {
'Authorization': f'token {pages_repo_token}',
'Accept': 'application/vnd.github.v3+json',
'Content-Type': 'application/json'
}
api_url = f"https://api.github.com/repos/{pages_repo_owner}/{pages_repo_name}/dispatches"
print("准备触发页面更新...")
print(f"目标仓库: {pages_repo_owner}/{pages_repo_name}")
print(f"版本: {client_payload.get('version')}")
print(f"更新日志: {'已包含 (' + str(len(changelog)) + ' 字符)' if changelog else '未包含'}")
print(f"下载链接: {'已包含 (' + str(len(download_links)) + ' 项)' if download_links else '未包含'}")
print(f"API URL: {api_url}")
invoke_repository_dispatch(api_url, headers, client_payload, max_retries=15, retry_delay=5)
'@
$scriptPath = Join-Path $env:TEMP "trigger_pages_update_$(New-Guid).py"
$scriptContent | Set-Content -Path $scriptPath -Encoding UTF8 -NoNewline
try {
python $scriptPath
if ($LASTEXITCODE -ne 0) {
Write-Error "Python 脚本执行失败,退出码: $LASTEXITCODE"
exit $LASTEXITCODE
}
} finally {
if (Test-Path $scriptPath) {
Remove-Item -Path $scriptPath -Force
}
}
shell: pwsh