Skip to content

Update dotnet-ci.yaml #80

Update dotnet-ci.yaml

Update dotnet-ci.yaml #80

Workflow file for this run

name: .NET CI/CD - Multi-Platform Release
on:
push:
branches: [ main, master ]
paths-ignore:
- '**.md'
- '**.gitignore'
- '.github/**/*.yml'
pull_request:
branches: [ main, master ]
workflow_dispatch:
inputs:
tagSuffix:
description: 'Tag后缀(可选,如 beta1、rc2)'
required: false
default: ''
type: string
preRelease:
description: '是否标记为预发布版本'
required: false
default: 'false'
type: boolean
env:
SOLUTION_PATH: ./src/GeneralUpdate.Tool.Avalonia.sln
PUBLISH_DIR: ./publish
PROJECT_NAME: GeneralUpdate.Tool.Avalonia
DOTNET_SDK_VERSION: '8.0.x' # 显式指定SDK版本,避免自动升级到预览版
jobs:
build:
name: Build ${{ matrix.os }} - ${{ matrix.target-os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [windows-latest, ubuntu-latest]
target-os: [win-x64, linux-x64]
exclude:
- os: windows-latest
target-os: linux-x64
- os: ubuntu-latest
target-os: win-x64
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
lfs: false
# 强制指定SDK版本,避免使用预览版(如10.0)
- name: Setup .NET SDK ${{ env.DOTNET_SDK_VERSION }}
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ env.DOTNET_SDK_VERSION }}
cache: true
cache-dependency-path: |
${{ env.SOLUTION_PATH }}
**/packages.lock.json
# 修复核心:拆分锁文件生成和依赖还原(避免参数冲突)
- name: Generate packages.lock.json (if missing)
run: |
# 仅当锁文件不存在时生成(避免覆盖已有锁文件)
if [ ! -f "./src/packages.lock.json" ]; then
echo "🔍 未找到锁文件,开始生成..."
dotnet restore ${{ env.SOLUTION_PATH }} --generate-lock-file
if [ $? -ne 0 ]; then
echo "❌ 锁文件生成失败"
exit 1
fi
echo "✅ 锁文件生成成功"
else
echo "ℹ️ 锁文件已存在,跳过生成"
fi
shell: bash
- name: Restore dependencies (locked mode)
run: |
# 使用已存在的锁文件还原依赖(锁定模式)
dotnet restore ${{ env.SOLUTION_PATH }} --locked-mode
if [ $? -ne 0 ]; then
echo "❌ 依赖还原失败,请检查锁文件或依赖配置"
exit 1
fi
echo "✅ 依赖还原成功"
shell: bash
- name: Build Release version
run: |
dotnet build ${{ env.SOLUTION_PATH }} \
-c Release \
-r ${{ matrix.target-os }} \
--no-restore \
/p:WarningLevel=1
shell: bash
- name: Publish application
run: |
mkdir -p ${{ env.PUBLISH_DIR }}/${{ matrix.target-os }}
dotnet publish ${{ env.SOLUTION_PATH }} \
-c Release \
-r ${{ matrix.target-os }} \
-o ${{ env.PUBLISH_DIR }}/${{ matrix.target-os }} \
--no-build \
--self-contained true \
/p:PublishSingleFile=true \
/p:PublishTrimmed=true \
/p:TrimUnusedDependencies=true \
/p:DebugType=None \
/p:DebugSymbols=false \
/p:AssemblyVersion=1.0.${{ github.run_number }} \
/p:FileVersion=1.0.${{ github.run_number }} \
/p:UseAppHost=true
if [ $(ls -A ${{ env.PUBLISH_DIR }}/${{ matrix.target-os }} | wc -l) -eq 0 ]; then
echo "❌ 发布目录为空,发布失败"
exit 1
fi
shell: bash
- name: Set execute permission (Linux only)
if: matrix.target-os == 'linux-x64'
run: |
chmod +x ${{ env.PUBLISH_DIR }}/${{ matrix.target-os }}/${{ env.PROJECT_NAME }}
if [ ! -x ${{ env.PUBLISH_DIR }}/${{ matrix.target-os }}/${{ env.PROJECT_NAME }} ]; then
echo "❌ Linux可执行文件权限设置失败"
exit 1
fi
shell: bash
- name: Package release files
id: package
run: |
DATE=$(date +%Y%m%d)
ZIP_NAME="${{ env.PROJECT_NAME }}_${{ matrix.target-os }}_${DATE}.zip"
ZIP_PATH="${{ env.PUBLISH_DIR }}/${ZIP_NAME}"
if [[ "${{ matrix.os }}" == "windows-latest" ]]; then
powershell Compress-Archive -Path "${{ env.PUBLISH_DIR }}/${{ matrix.target-os }}/*" -DestinationPath "$ZIP_PATH" -Force
else
zip -r "$ZIP_PATH" "${{ env.PUBLISH_DIR }}/${{ matrix.target-os }}/*"
fi
if [ ! -f "$ZIP_PATH" ]; then
echo "❌ 压缩包生成失败"
exit 1
fi
echo "zip_name=$ZIP_NAME" >> $GITHUB_OUTPUT
echo "zip_path=$ZIP_PATH" >> $GITHUB_OUTPUT
echo "✅ 压缩包生成成功:$ZIP_NAME"
shell: bash
- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.target-os }}_artifact
path: ${{ steps.package.outputs.zip_path }}
retention-days: 7
if-no-files-found: error
release:
name: Create GitHub Release
runs-on: ubuntu-latest
needs: build
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
permissions:
contents: write
steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: ./artifacts
merge-multiple: false
- name: Configure Git user
run: |
git config --global user.name "GitHub Actions"
git config --global user.email "actions@github.com"
git fetch --tags
shell: bash
- name: Generate date-based Tag
id: create_tag
run: |
BASE_TAG="v$(date +%Y%m%d)"
TAG_SUFFIX="${{ github.event.inputs.tagSuffix }}"
if [ -n "$TAG_SUFFIX" ]; then
FINAL_TAG="${BASE_TAG}-${TAG_SUFFIX}"
else
FINAL_TAG="${BASE_TAG}"
fi
if git rev-parse "$FINAL_TAG" >/dev/null 2>&1; then
echo "ℹ️ Tag $FINAL_TAG 已存在,跳过创建"
else
git tag "$FINAL_TAG"
git push origin "$FINAL_TAG"
echo "✅ 成功创建Tag:$FINAL_TAG"
fi
echo "tag_name=$FINAL_TAG" >> $GITHUB_OUTPUT
shell: bash
- name: Create Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.create_tag.outputs.tag_name }}
name: Release ${{ steps.create_tag.outputs.tag_name }}
body: |
## 🚀 自动构建发布
- 构建日期:${{ steps.create_tag.outputs.tag_name }}
- 构建编号:${{ github.run_number }}
- 包含平台:Windows x64 / Linux x64
- 构建模式:Release | 单文件 | 自包含 | 依赖裁剪
files: |
./artifacts/win-x64_artifact/*.zip
./artifacts/linux-x64_artifact/*.zip
prerelease: ${{ github.event.inputs.preRelease == 'true' || github.event.inputs.tagSuffix != '' }}
draft: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Cleanup artifacts
if: always()
run: |
rm -rf ./artifacts
echo "✅ 产物清理完成"
shell: bash