mirror of
https://github.com/AstrBotDevs/AstrBot
synced 2026-07-17 17:51:20 +08:00
280
.github/workflows/release.yml
vendored
280
.github/workflows/release.yml
vendored
@@ -4,9 +4,6 @@ on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
schedule:
|
||||
# Daily at 00:00 UTC
|
||||
- cron: "0 0 * * *"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
@@ -21,133 +18,15 @@ permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
resolve-release-context:
|
||||
name: Resolve Release Context
|
||||
runs-on: ubuntu-24.04
|
||||
outputs:
|
||||
checkout_ref: ${{ steps.checkout-ref.outputs.ref }}
|
||||
tag: ${{ steps.tag.outputs.tag }}
|
||||
nightly_tag: ${{ steps.nightly-tag.outputs.nightly_tag }}
|
||||
repo_slug: ${{ steps.repo-slug.outputs.repo_slug }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Resolve nightly tag
|
||||
id: nightly-tag
|
||||
shell: bash
|
||||
run: |
|
||||
nightly_tag="$(python3 -m scripts.release.print_release_constant NIGHTLY_TAG)"
|
||||
if [ -z "$nightly_tag" ]; then
|
||||
echo "Failed to resolve NIGHTLY_TAG from astrbot/core/release_constants.py." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "nightly_tag=$nightly_tag" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Resolve repository slug
|
||||
id: repo-slug
|
||||
shell: bash
|
||||
run: |
|
||||
repo_slug="$(python3 -m scripts.release.print_release_constant GITHUB_REPO_SLUG)"
|
||||
if [ -z "$repo_slug" ]; then
|
||||
echo "Failed to resolve GITHUB_REPO_SLUG from astrbot/core/release_constants.py." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "repo_slug=$repo_slug" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Resolve checkout ref
|
||||
id: checkout-ref
|
||||
shell: bash
|
||||
run: |
|
||||
event_name="${{ github.event_name }}"
|
||||
nightly_tag="${{ steps.nightly-tag.outputs.nightly_tag }}"
|
||||
input_tag=""
|
||||
input_ref=""
|
||||
if [ "$event_name" = "workflow_dispatch" ]; then
|
||||
input_tag="$(jq -r '.inputs.tag // ""' "$GITHUB_EVENT_PATH")"
|
||||
input_ref="$(jq -r '.inputs.ref // ""' "$GITHUB_EVENT_PATH")"
|
||||
fi
|
||||
default_branch="${{ github.event.repository.default_branch }}"
|
||||
if [ -z "$default_branch" ]; then
|
||||
default_branch="master"
|
||||
fi
|
||||
|
||||
if [ "$event_name" = "schedule" ]; then
|
||||
ref="refs/heads/${default_branch}"
|
||||
elif [ "$event_name" = "workflow_dispatch" ] && [ -n "$input_ref" ]; then
|
||||
ref="$input_ref"
|
||||
elif [ "$event_name" = "workflow_dispatch" ] && [ "$input_tag" = "$nightly_tag" ]; then
|
||||
ref="refs/heads/${default_branch}"
|
||||
elif [ -n "$input_ref" ]; then
|
||||
ref="$input_ref"
|
||||
else
|
||||
ref="${{ github.ref }}"
|
||||
fi
|
||||
|
||||
echo "ref=$ref" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Switch repository to release ref
|
||||
shell: bash
|
||||
run: |
|
||||
target_ref="${{ steps.checkout-ref.outputs.ref }}"
|
||||
if [ -z "$target_ref" ]; then
|
||||
echo "Resolved checkout ref is empty." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! git checkout --force "$target_ref" >/tmp/git_checkout_ref.log 2>&1; then
|
||||
if ! git fetch --force origin "$target_ref" >/tmp/git_fetch_ref.log 2>&1; then
|
||||
echo "Failed to fetch checkout ref: $target_ref" >&2
|
||||
cat /tmp/git_fetch_ref.log >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
git checkout --force FETCH_HEAD
|
||||
fi
|
||||
|
||||
- name: Resolve tag
|
||||
id: tag
|
||||
shell: bash
|
||||
run: |
|
||||
event_name="${{ github.event_name }}"
|
||||
nightly_tag="${{ steps.nightly-tag.outputs.nightly_tag }}"
|
||||
dispatch_tag=""
|
||||
if [ "$event_name" = "workflow_dispatch" ]; then
|
||||
dispatch_tag="$(jq -r '.inputs.tag // ""' "$GITHUB_EVENT_PATH")"
|
||||
fi
|
||||
|
||||
if [ "$event_name" = "schedule" ]; then
|
||||
tag="$nightly_tag"
|
||||
elif [ "$event_name" = "push" ]; then
|
||||
tag="${GITHUB_REF_NAME}"
|
||||
elif [ -n "$dispatch_tag" ]; then
|
||||
tag="$dispatch_tag"
|
||||
else
|
||||
# workflow_dispatch without explicit tag should default to latest stable v-tag.
|
||||
tag="$(git tag --list 'v*' --sort=-version:refname | grep -E '^v[0-9]+(\.[0-9]+)*$' | head -n1)"
|
||||
if [ -z "$tag" ]; then
|
||||
echo "Failed to resolve latest stable v-tag." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [ -z "$tag" ]; then
|
||||
echo "Failed to resolve tag." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "tag=$tag" >> "$GITHUB_OUTPUT"
|
||||
|
||||
verify-core:
|
||||
name: Verify Core Quality Gate
|
||||
runs-on: ubuntu-24.04
|
||||
needs:
|
||||
- resolve-release-context
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ needs.resolve-release-context.outputs.checkout_ref }}
|
||||
ref: ${{ inputs.ref || github.ref }}
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
@@ -165,8 +44,6 @@ jobs:
|
||||
build-dashboard:
|
||||
name: Build Dashboard
|
||||
runs-on: ubuntu-24.04
|
||||
needs:
|
||||
- resolve-release-context
|
||||
env:
|
||||
R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }}
|
||||
R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
|
||||
@@ -176,7 +53,24 @@ jobs:
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ needs.resolve-release-context.outputs.checkout_ref }}
|
||||
ref: ${{ inputs.ref || github.ref }}
|
||||
|
||||
- name: Resolve tag
|
||||
id: tag
|
||||
shell: bash
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "push" ]; then
|
||||
tag="${GITHUB_REF_NAME}"
|
||||
elif [ -n "${{ inputs.tag }}" ]; then
|
||||
tag="${{ inputs.tag }}"
|
||||
else
|
||||
tag="$(git describe --tags --abbrev=0)"
|
||||
fi
|
||||
if [ -z "$tag" ]; then
|
||||
echo "Failed to resolve tag." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "tag=$tag" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
@@ -195,23 +89,23 @@ jobs:
|
||||
run: |
|
||||
pnpm --dir dashboard install --frozen-lockfile
|
||||
pnpm --dir dashboard run build
|
||||
echo "${{ needs.resolve-release-context.outputs.tag }}" > dashboard/dist/assets/version
|
||||
echo "${{ steps.tag.outputs.tag }}" > dashboard/dist/assets/version
|
||||
cd dashboard
|
||||
zip -r "AstrBot-${{ needs.resolve-release-context.outputs.tag }}-dashboard.zip" dist
|
||||
zip -r "AstrBot-${{ steps.tag.outputs.tag }}-dashboard.zip" dist
|
||||
|
||||
- name: Upload dashboard artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: Dashboard-${{ needs.resolve-release-context.outputs.tag }}
|
||||
name: Dashboard-${{ steps.tag.outputs.tag }}
|
||||
if-no-files-found: error
|
||||
path: dashboard/AstrBot-${{ needs.resolve-release-context.outputs.tag }}-dashboard.zip
|
||||
path: dashboard/AstrBot-${{ steps.tag.outputs.tag }}-dashboard.zip
|
||||
|
||||
- name: Upload dashboard package to Cloudflare R2
|
||||
if: ${{ env.R2_ACCOUNT_ID != '' && env.R2_ACCESS_KEY_ID != '' && env.R2_SECRET_ACCESS_KEY != '' && needs.resolve-release-context.outputs.tag != needs.resolve-release-context.outputs.nightly_tag }}
|
||||
if: ${{ env.R2_ACCOUNT_ID != '' && env.R2_ACCESS_KEY_ID != '' && env.R2_SECRET_ACCESS_KEY != '' }}
|
||||
env:
|
||||
R2_BUCKET_NAME: "astrbot"
|
||||
R2_OBJECT_NAME: "astrbot-webui-latest.zip"
|
||||
VERSION_TAG: ${{ needs.resolve-release-context.outputs.tag }}
|
||||
VERSION_TAG: ${{ steps.tag.outputs.tag }}
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update
|
||||
@@ -235,11 +129,7 @@ jobs:
|
||||
publish-release:
|
||||
name: Publish GitHub Release
|
||||
runs-on: ubuntu-24.04
|
||||
concurrency:
|
||||
group: ${{ needs.resolve-release-context.outputs.tag == needs.resolve-release-context.outputs.nightly_tag && 'nightly-release' || format('release-{0}', needs.resolve-release-context.outputs.tag) }}
|
||||
cancel-in-progress: ${{ needs.resolve-release-context.outputs.tag == needs.resolve-release-context.outputs.nightly_tag }}
|
||||
needs:
|
||||
- resolve-release-context
|
||||
- verify-core
|
||||
- build-dashboard
|
||||
steps:
|
||||
@@ -247,51 +137,29 @@ jobs:
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ needs.resolve-release-context.outputs.checkout_ref }}
|
||||
ref: ${{ inputs.ref || github.ref }}
|
||||
|
||||
- name: Resolve release title
|
||||
id: release-meta
|
||||
- name: Resolve tag
|
||||
id: tag
|
||||
shell: bash
|
||||
run: |
|
||||
tag="${{ needs.resolve-release-context.outputs.tag }}"
|
||||
nightly_tag="${{ needs.resolve-release-context.outputs.nightly_tag }}"
|
||||
if [ "$tag" = "$nightly_tag" ]; then
|
||||
if ! short_sha="$(git rev-parse --short=8 HEAD 2>/tmp/git_rev_parse_error.log)"; then
|
||||
echo "Failed to resolve HEAD short SHA for nightly title." >&2
|
||||
cat /tmp/git_rev_parse_error.log >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
base_version="$(git tag --list 'v*' --sort=-version:refname | grep -E '^v[0-9]+(\.[0-9]+)*$' | head -n1)"
|
||||
if [ -z "$base_version" ]; then
|
||||
base_version="v0.0.0"
|
||||
fi
|
||||
title="${base_version}-${nightly_tag}-${short_sha}"
|
||||
if [ "${{ github.event_name }}" = "push" ]; then
|
||||
tag="${GITHUB_REF_NAME}"
|
||||
elif [ -n "${{ inputs.tag }}" ]; then
|
||||
tag="${{ inputs.tag }}"
|
||||
else
|
||||
base_version="$tag"
|
||||
title="$tag"
|
||||
tag="$(git describe --tags --abbrev=0)"
|
||||
fi
|
||||
echo "title=$title" >> "$GITHUB_OUTPUT"
|
||||
echo "base_version=$base_version" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Force-update nightly tag
|
||||
if: ${{ needs.resolve-release-context.outputs.tag == needs.resolve-release-context.outputs.nightly_tag }}
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
shell: bash
|
||||
run: |
|
||||
nightly_tag="${{ needs.resolve-release-context.outputs.nightly_tag }}"
|
||||
if ! current_sha="$(git rev-parse HEAD 2>/tmp/git_rev_parse_error.log)"; then
|
||||
echo "Failed to resolve HEAD SHA before updating nightly tag." >&2
|
||||
cat /tmp/git_rev_parse_error.log >&2 || true
|
||||
if [ -z "$tag" ]; then
|
||||
echo "Failed to resolve tag." >&2
|
||||
exit 1
|
||||
fi
|
||||
git tag -f "$nightly_tag" "${current_sha}"
|
||||
git push --force origin "refs/tags/${nightly_tag}"
|
||||
echo "tag=$tag" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Download dashboard artifact
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: Dashboard-${{ needs.resolve-release-context.outputs.tag }}
|
||||
name: Dashboard-${{ steps.tag.outputs.tag }}
|
||||
path: release-assets
|
||||
|
||||
|
||||
@@ -299,32 +167,10 @@ jobs:
|
||||
id: notes
|
||||
shell: bash
|
||||
run: |
|
||||
tag="${{ needs.resolve-release-context.outputs.tag }}"
|
||||
nightly_tag="${{ needs.resolve-release-context.outputs.nightly_tag }}"
|
||||
if [ "$tag" = "$nightly_tag" ]; then
|
||||
note_file="changelogs/${{ steps.tag.outputs.tag }}.md"
|
||||
if [ ! -f "$note_file" ]; then
|
||||
note_file="$(mktemp)"
|
||||
if [ -f "scripts/release/generate_nightly_release_notes.py" ]; then
|
||||
python3 -m scripts.release.generate_nightly_release_notes \
|
||||
--base-tag "${{ steps.release-meta.outputs.base_version }}" \
|
||||
--repo "${{ needs.resolve-release-context.outputs.repo_slug }}" \
|
||||
--output "$note_file"
|
||||
else
|
||||
short_sha="$(git rev-parse --short=8 HEAD)"
|
||||
echo "Nightly notes script is missing at this ref; using fallback notes."
|
||||
{
|
||||
echo "## What's Changed"
|
||||
echo ""
|
||||
echo "- Baseline tag: \`${{ steps.release-meta.outputs.base_version }}\`"
|
||||
echo "- Nightly commit: \`$short_sha\`"
|
||||
echo "- No changes summary generator available in this ref."
|
||||
} > "$note_file"
|
||||
fi
|
||||
else
|
||||
note_file="changelogs/${tag}.md"
|
||||
if [ ! -f "$note_file" ]; then
|
||||
note_file="$(mktemp)"
|
||||
echo "Release ${tag}" > "$note_file"
|
||||
fi
|
||||
echo "Release ${{ steps.tag.outputs.tag }}" > "$note_file"
|
||||
fi
|
||||
echo "file=$note_file" >> "$GITHUB_OUTPUT"
|
||||
|
||||
@@ -333,18 +179,9 @@ jobs:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
shell: bash
|
||||
run: |
|
||||
tag="${{ needs.resolve-release-context.outputs.tag }}"
|
||||
title="${{ steps.release-meta.outputs.title }}"
|
||||
nightly_tag="${{ needs.resolve-release-context.outputs.nightly_tag }}"
|
||||
if [ "$tag" = "$nightly_tag" ]; then
|
||||
pre_flag="--prerelease"
|
||||
else
|
||||
pre_flag=""
|
||||
fi
|
||||
tag="${{ steps.tag.outputs.tag }}"
|
||||
if ! gh release view "$tag" >/dev/null 2>&1; then
|
||||
gh release create "$tag" --title "$title" --notes-file "${{ steps.notes.outputs.file }}" $pre_flag
|
||||
elif [ "$tag" = "$nightly_tag" ]; then
|
||||
gh release edit "$tag" --title "$title" --notes-file "${{ steps.notes.outputs.file }}" --prerelease
|
||||
gh release create "$tag" --title "$tag" --notes-file "${{ steps.notes.outputs.file }}"
|
||||
fi
|
||||
|
||||
- name: Remove stale assets from release
|
||||
@@ -352,10 +189,10 @@ jobs:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
shell: bash
|
||||
run: |
|
||||
tag="${{ needs.resolve-release-context.outputs.tag }}"
|
||||
tag="${{ steps.tag.outputs.tag }}"
|
||||
while IFS= read -r asset; do
|
||||
case "$asset" in
|
||||
AstrBot-*-dashboard.zip)
|
||||
*.AppImage|*.dmg|*.zip|*.exe|*.blockmap)
|
||||
gh release delete-asset "$tag" "$asset" -y || true
|
||||
;;
|
||||
esac
|
||||
@@ -366,34 +203,49 @@ jobs:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
shell: bash
|
||||
run: |
|
||||
tag="${{ needs.resolve-release-context.outputs.tag }}"
|
||||
gh release upload "$tag" "release-assets/AstrBot-${tag}-dashboard.zip" --clobber
|
||||
tag="${{ steps.tag.outputs.tag }}"
|
||||
gh release upload "$tag" release-assets/* --clobber
|
||||
|
||||
publish-pypi:
|
||||
name: Publish PyPI
|
||||
if: ${{ needs.resolve-release-context.outputs.tag != needs.resolve-release-context.outputs.nightly_tag }}
|
||||
runs-on: ubuntu-24.04
|
||||
needs:
|
||||
- resolve-release-context
|
||||
- publish-release
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ needs.resolve-release-context.outputs.checkout_ref }}
|
||||
ref: ${{ inputs.ref || github.ref }}
|
||||
|
||||
- name: Resolve tag
|
||||
id: tag
|
||||
shell: bash
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "push" ]; then
|
||||
tag="${GITHUB_REF_NAME}"
|
||||
elif [ -n "${{ inputs.tag }}" ]; then
|
||||
tag="${{ inputs.tag }}"
|
||||
else
|
||||
tag="$(git describe --tags --abbrev=0)"
|
||||
fi
|
||||
if [ -z "$tag" ]; then
|
||||
echo "Failed to resolve tag." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "tag=$tag" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Download dashboard artifact
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: Dashboard-${{ needs.resolve-release-context.outputs.tag }}
|
||||
name: Dashboard-${{ steps.tag.outputs.tag }}
|
||||
path: dashboard-artifact
|
||||
|
||||
- name: Unpack dashboard dist into package tree
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p astrbot/dashboard/dist
|
||||
unzip -q "dashboard-artifact/AstrBot-${{ needs.resolve-release-context.outputs.tag }}-dashboard.zip" -d dashboard-artifact/unpacked
|
||||
unzip -q "dashboard-artifact/AstrBot-${{ steps.tag.outputs.tag }}-dashboard.zip" -d dashboard-artifact/unpacked
|
||||
cp -r dashboard-artifact/unpacked/dist/. astrbot/dashboard/dist/
|
||||
|
||||
- name: Set up Python
|
||||
|
||||
Reference in New Issue
Block a user