Skip to content

feat: 脚本程序区分启动器模式和直接启动模式 #36

feat: 脚本程序区分启动器模式和直接启动模式

feat: 脚本程序区分启动器模式和直接启动模式 #36

Workflow file for this run

name: Build and Release
on:
push:
tags:
- 'v*'
pull_request:
types:
- opened
- synchronize
- reopened
- labeled
workflow_dispatch:
inputs:
create_release:
description: 'Create Release'
required: true
default: false
type: boolean
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env:
CREATE_RELEASE: ${{ (github.event_name == 'workflow_dispatch' && inputs.create_release == true) || startsWith(github.ref, 'refs/tags/') }}
jobs:
build:
if: ${{ github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'build') }}
runs-on: windows-latest
outputs:
version: ${{ steps.get_version.outputs.version }}
tag: ${{ steps.get_version.outputs.tag }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Get version
id: get_version
shell: pwsh
run: |
if ($env:GITHUB_REF -like 'refs/tags/*') {
# 已由 tag 推送触发,直接使用该 tag 作为版本
$version = $env:GITHUB_REF.Substring(10)
$tag = $version
} elseif ($env:GITHUB_EVENT_NAME -eq 'pull_request') {
# PR 构建只产出测试包,不创建 / 推送 tag
$shortSha = $env:GITHUB_SHA.Substring(0, 7)
$version = "pr-${{ github.event.pull_request.number }}-$shortSha"
$tag = $version
} else {
# 手动 workflow_dispatch 触发:使用 git 的语义化版本排序,选出最新 tag,然后生成 / 递增 beta 版本
# --refs 可避免出现带 ^{} 的 peeled 行,--sort=-version:refname 以版本名倒序排序,'v*' 仅匹配语义化版本前缀
$latestRef = git ls-remote --refs --tags --sort=-version:refname origin 'v*' |
Where-Object { $_ -match 'refs/tags/(v\d+\.\d+\.\d+(?:-beta\.\d+)?)$' } |
Select-Object -First 1
if (-not $latestRef) {
# 仓库还没有任何符合语义版本的 tag,初始化为 v0.1.0-beta.1
$baseVersion = 'v0.1.0'
$betaNumber = 1
$tag = "$baseVersion-beta.$betaNumber"
} else {
# 行格式: <hash>\trefs/tags/<tagname>
if ($latestRef -match 'refs/tags/(.+)$') {
$latestTag = $matches[1]
} else {
throw "无法从 ls-remote 输出中解析最新 tag:$latestRef"
}
if ($latestTag -match '^(v\d+\.\d+\.\d+)-beta\.(\d+)$') {
# 最新即为 beta,直接在 beta 编号上 +1
$baseVersion = $matches[1]
$betaNumber = [int]$matches[2] + 1
$tag = "$baseVersion-beta.$betaNumber"
} else {
# 最新为稳定版本,从该稳定版本开始新的 beta 序列
$latestTag -match '^(v\d+\.\d+\.)(\d+)$'
$baseVersion = $matches[1] + ([int]$matches[2] + 1)
$betaNumber = 1
$tag = "$baseVersion-beta.$betaNumber"
}
}
$version = $tag
git config --global user.email "actions@github.com"
git config --global user.name "GitHub Actions"
# 创建并推送新 beta tag
git tag $tag
git push origin $tag
}
echo "version=$version" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
echo "tag=$tag" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
echo "__version__ = '$version'" | Out-File -FilePath src/one_dragon/version.py -Encoding utf8
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11.9'
- name: Install uv
shell: pwsh
run: |
Invoke-WebRequest -Uri https://astral.sh/uv/install.ps1 | Invoke-Expression
- name: Create virtual environment and install dependencies
shell: pwsh
run: |
uv sync
- name: Download and extract UPX into venv Scripts
shell: pwsh
run: |
$venvScripts = ".\.venv\Scripts"
$upxDir = Join-Path $venvScripts "upx"
$sourceUpxPath = Join-Path $upxDir "upx-4.2.3-win64" "upx.exe"
$destinationUpxPath = Join-Path $venvScripts "upx.exe"
$zipPath = "upx.zip"
Invoke-WebRequest -Uri "https://github.com/upx/upx/releases/download/v4.2.3/upx-4.2.3-win64.zip" -OutFile $zipPath
Expand-Archive -Path $zipPath -DestinationPath $upxDir -Force
Move-Item -Path $sourceUpxPath -Destination $destinationUpxPath -Force
Remove-Item -Path $upxDir -Recurse -Force
Remove-Item -Path $zipPath -Force
- name: Build executables
shell: pwsh
run: |
.\.venv\Scripts\Activate.ps1
cd deploy
pyinstaller "OneDragon ScriptChainer.spec"
pyinstaller "OneDragon ScriptChainer Runner.spec"
- name: Upload Editor
if: ${{ env.CREATE_RELEASE == 'false' }}
uses: actions/upload-artifact@v4
with:
name: Editor
path: deploy/dist/OneDragon ScriptChainer.exe
- name: Upload Runner
if: ${{ env.CREATE_RELEASE == 'false' }}
uses: actions/upload-artifact@v4
with:
name: Runner
path: deploy/dist/OneDragon ScriptChainer Runner.exe
- name: Upload Dist
if: ${{ env.CREATE_RELEASE == 'true' }}
uses: actions/upload-artifact@v4
with:
name: dist
if-no-files-found: error
path: deploy/dist
release:
runs-on: windows-latest
needs: build
if: ${{ (github.event_name == 'workflow_dispatch' && inputs.create_release == true) || startsWith(github.ref, 'refs/tags/') }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download dist
uses: actions/download-artifact@v4
with:
name: dist
path: .
- name: Prepare release packages
shell: pwsh
env:
RELEASE_VERSION: ${{ needs.build.outputs.version }}
run: |
$version = $env:RELEASE_VERSION
# 在根目录打包两个 exe
Compress-Archive -Path "OneDragon ScriptChainer.exe","OneDragon ScriptChainer Runner.exe" -DestinationPath "OneDragon-ScriptChainer-$version.zip" -Force
- name: Generate Changelog
id: changelog
shell: pwsh
run: |
$current_version_tag = "${{ needs.build.outputs.version }}" # 从 get_version 步骤获取的标签
$commits = @()
if ($env:GITHUB_REF -like 'refs/tags/*') {
# 这是由标签触发的发布
# 尝试查找当前标签提交的父提交上的最新标签
$previous_tag_candidate = $(git describe --tags --abbrev=0 "$current_version_tag^" 2>$null)
if ($previous_tag_candidate) {
Write-Host "正在生成从 $previous_tag_candidate 到 $current_version_tag 的更新日志"
$commits = git log --pretty=format:"%s|%h" "$previous_tag_candidate..$current_version_tag"
} else {
Write-Host "未找到相对于 $current_version_tag^ 的上一个标签。列出 $current_version_tag 的最后10个提交。"
# 这可能是第一个标签。列出导致它的提交。
$commits = git log --pretty=format:"%s|%h" -n 10 "$current_version_tag"
}
} else {
# 这是手动 workflow_dispatch 或分支推送
Write-Host "手动或分支构建。列出 HEAD 的最后5个提交。"
$commits = git log --pretty=format:"%s|%h" -n 5 HEAD
}
# 按前缀分类提交
$categories = @{
"feat" = @()
"fix" = @()
"perf" = @()
"refactor" = @()
"style" = @()
"docs" = @()
"test" = @()
"ci" = @()
"build" = @()
"chore" = @()
"revert" = @()
"other" = @()
}
foreach ($commit in $commits) {
if ($commit -match "^(.+)\|(.+)$") {
$message = $matches[1]
$hash = $matches[2]
# 兼容带 scope 的 Conventional Commits,例如 feat(ui): xxx / feat(ui)!: xxx
if ($message -match "^([A-Za-z]+)(?:\(([^)!]+)\))?(!)?:\s*(.*)$") {
$prefix = $matches[1].Trim().ToLower()
$scope = if ($null -ne $matches[2]) { $matches[2].Trim() } else { "" }
$content = $matches[4].Trim()
if (-not [string]::IsNullOrWhiteSpace($scope)) {
$content = "$($scope): $content"
}
# 检查前缀是否在已知分类中
if ($categories.ContainsKey($prefix)) {
$categories[$prefix] += "- $content ($hash)"
} else {
$categories["other"] += "- $message ($hash)"
}
} else {
$categories["other"] += "- $message ($hash)"
}
}
}
# 生成分类后的更新日志
$changelog_content = ""
$category_names = @{
"feat" = "✨ 新功能"
"fix" = "🐛 Bug 修复"
"perf" = "⚡ 性能优化"
"refactor" = "♻️ 代码重构"
"style" = "💄 样式调整"
"docs" = "📄 文档更新"
"test" = "✅ 测试"
"ci" = "👷 CI/CD"
"build" = "📦 构建"
"chore" = "🔧 杂项"
"revert" = "⏪ 回滚"
"other" = "📝 其他更改"
}
# 定义输出顺序
$ordered_keys = @("feat", "fix", "perf", "refactor", "style", "docs", "test", "ci", "build", "chore", "revert", "other")
foreach ($key in $ordered_keys) {
if ($categories[$key].Count -gt 0) {
if ($changelog_content -ne "") {
$changelog_content += "`n`n"
}
$changelog_content += "## $($category_names[$key])`n"
$changelog_content += ($categories[$key] -join "`n")
}
}
if ([string]::IsNullOrWhiteSpace($changelog_content)) {
$changelog_content = "没有新的更改或无法确定更新日志。"
}
$output_name = "clean_changelog"
$delimiter = "CHANGELOG_DELIMITER_$(New-Guid)"
echo "$output_name<<$delimiter" | Out-File -FilePath $env:GITHUB_OUTPUT -Append
echo $changelog_content | Out-File -FilePath $env:GITHUB_OUTPUT -Append
echo $delimiter | Out-File -FilePath $env:GITHUB_OUTPUT -Append
- name: Create Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.build.outputs.tag }}
name: "Release ${{ needs.build.outputs.version }}"
body: |
## OneDragon ScriptChainer ${{ needs.build.outputs.version }}
### 下载说明
- `OneDragon-ScriptChainer-${{ needs.build.outputs.version }}.zip` - 包含编辑器和运行器的完整包
### 使用方法
1. 下载 `OneDragon-ScriptChainer-${{ needs.build.outputs.version }}.zip`
2. 解压到任意目录
3. 运行 `OneDragon ScriptChainer.exe` 创建和编辑脚本链
4. 运行 `OneDragon ScriptChainer Runner.exe` 执行脚本链
### 命令行参数
`OneDragon ScriptChainer.exe` 支持以下参数:
| 参数 | 说明 |
|------|------|
| `-o, --onedragon` | 一条龙运行模式(跳过 GUI 直接执行脚本链) |
| `--chain <名称>` | 指定脚本链名称,默认 `01`(仅 `--onedragon` 模式) |
| `-s, --shutdown [秒数]` | 运行后关机,可指定延迟秒数,默认 60 秒(仅 `--onedragon` 模式) |
| `-v, --version` | 显示版本号 |
示例: `OneDragon ScriptChainer.exe -o --chain 02 -s 120`
[更多参考](https://one-dragon.com/tools/zh/script_chainer.html)
# 更新内容
${{ steps.changelog.outputs.clean_changelog }}
files: |
OneDragon-ScriptChainer-${{ needs.build.outputs.version }}.zip
generate_release_notes: false
prerelease: ${{ contains(needs.build.outputs.version, '-beta.') }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Trigger MirrorChyanUploading
if: ${{ github.repository_owner == 'OneDragon-Anything' }}
shell: bash
run: |
gh workflow run --repo $GITHUB_REPOSITORY mirrorchyan-release.yml -f tag=${{ needs.build.outputs.tag }}
gh workflow run --repo $GITHUB_REPOSITORY mirrorchyan-release_note.yml -f tag=${{ needs.build.outputs.tag }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}