mirror of
https://github.com/TencentCloud/Octop.git
synced 2026-10-20 06:19:17 +08:00
* feat(workflows): add COS upload functionality for release assets - Implemented a new workflow to upload GitHub Release assets to COS. - Updated existing workflows to trigger the upload process after release creation. - Enhanced documentation within workflows to clarify asset handling and upload procedures. * fix(workflows): update COS upload paths in workflows and scripts - Changed asset upload paths in multiple workflow files to use the new format: `octop/release/<version>/`. - Updated documentation comments to reflect the new upload structure for clarity. - Adjusted the upload script to align with the updated path conventions. * fix(workflows): upload to COS after skipped package jobs GitHub skips a later reusable workflow when an earlier job in the chain was skipped, even if the release job succeeded. Attach-only desktop runs and FnOS native skips hit that path. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ci): pin the published coscli v1.0.9 checksum The linux-amd64 asset hash no longer matches the value baked into the upload script, so COS uploads stop before any object is sent. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ci): upload release files to COS concurrently A sequential coscli loop left each multi-hundred-megabyte package waiting on the previous one. Start every file at once and fail the job if any upload fails. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ci): stream coscli process logs during release upload Process logs were disabled, so a running upload showed no throughput. Write one log per file and follow it on stdout. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ci): keep per-file coscli configs named .yaml coscli rejects a config path that does not end in .yaml. Parallel uploads appended the package name after that suffix, so every file failed before transfer. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ci): keep Python wheel and sdist off COS Those packages already go to PyPI and the GitHub Release. COS should only receive desktop installers and FnOS packages. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ci): read COS release settings from secrets Reusable workflows only see secrets that callers pass explicitly. Bucket, region, and endpoint now travel with the existing COS credentials. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
172 lines
5.1 KiB
YAML
172 lines
5.1 KiB
YAML
name: Release
|
||
|
||
# 版本标签 v* → 测包、发 PyPI、建 GitHub Release,再级联:
|
||
# - Sync Main Into Develop
|
||
# - Build Octop FPK(复用本 Release 的 wheel;等待 docker-publish 的多架构 GHCR 镜像)
|
||
#
|
||
# 与 docker-publish.yml / octop-desktop.yml 并行(由 Auto Tag 同时 dispatch,
|
||
# 或人工 push v* tag 同时触发)。wheel / sdist 只发 PyPI 和 GitHub Release。
|
||
# 桌面安装包与 FnOS FPK 挂到同一 GitHub Release 后,再上传到同一个 COS 版本目录。
|
||
|
||
on:
|
||
push:
|
||
tags:
|
||
- "v*"
|
||
# Allow Auto Tag On Release Merge to cascade after a GITHUB_TOKEN tag push
|
||
# (token-authored pushes do not retrigger push workflows).
|
||
workflow_dispatch:
|
||
|
||
permissions:
|
||
contents: write
|
||
actions: write
|
||
|
||
concurrency:
|
||
group: release-${{ github.ref }}
|
||
cancel-in-progress: false
|
||
|
||
jobs:
|
||
build:
|
||
name: Build distributions
|
||
runs-on: ubuntu-latest
|
||
if: startsWith(github.ref, 'refs/tags/v')
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
with:
|
||
fetch-depth: 0
|
||
|
||
- uses: astral-sh/setup-uv@v4
|
||
with:
|
||
enable-cache: true
|
||
|
||
- name: Set up Python
|
||
run: uv python install 3.12
|
||
|
||
- name: Set up Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: "20"
|
||
cache: npm
|
||
cache-dependency-path: dashboard/package-lock.json
|
||
|
||
- name: Install dependencies
|
||
run: make install
|
||
|
||
- name: Run tests
|
||
run: make test
|
||
|
||
- name: Build package
|
||
run: make build
|
||
|
||
- name: Upload distributions
|
||
uses: actions/upload-artifact@v4
|
||
with:
|
||
name: dist
|
||
path: dist/
|
||
|
||
publish:
|
||
name: Publish to PyPI
|
||
needs: build
|
||
runs-on: ubuntu-latest
|
||
environment: pypi
|
||
steps:
|
||
- name: Download distributions
|
||
uses: actions/download-artifact@v4
|
||
with:
|
||
name: dist
|
||
path: dist/
|
||
|
||
- name: Publish package
|
||
uses: pypa/gh-action-pypi-publish@release/v1
|
||
with:
|
||
password: ${{ secrets.PYPI_API_TOKEN }}
|
||
|
||
github-release:
|
||
name: Create GitHub Release
|
||
needs: publish
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
with:
|
||
fetch-depth: 0
|
||
|
||
- name: Download distributions
|
||
uses: actions/download-artifact@v4
|
||
with:
|
||
name: dist
|
||
path: dist/
|
||
|
||
- name: Extract version from tag
|
||
id: version
|
||
run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
|
||
|
||
- name: Extract release notes
|
||
run: |
|
||
version=${{ steps.version.outputs.version }}
|
||
if [ -f CHANGELOG.md ]; then
|
||
awk "/^## \[?$version\]?/{flag=1;next}/^## /{flag=0}flag" CHANGELOG.md > .release-notes.md || true
|
||
fi
|
||
if [ ! -s .release-notes.md ]; then
|
||
PREV=$(git tag --sort=-version:refname | grep -v "^${GITHUB_REF_NAME}$" | head -1)
|
||
{
|
||
echo "## What's changed"
|
||
echo ""
|
||
if [ -n "$PREV" ]; then
|
||
git log "${PREV}..${GITHUB_REF_NAME}" --oneline --no-decorate
|
||
else
|
||
git log --oneline --no-decorate | head -20
|
||
fi
|
||
echo ""
|
||
echo "## Install"
|
||
echo ""
|
||
echo '```bash'
|
||
echo "pip install octop==$version"
|
||
echo '```'
|
||
} > .release-notes.md
|
||
fi
|
||
if ! grep -q '^## Downloads' .release-notes.md; then
|
||
python3 scripts/release_download_links.py "$version" >> .release-notes.md
|
||
fi
|
||
|
||
- name: Create release
|
||
uses: softprops/action-gh-release@v2
|
||
with:
|
||
body_path: .release-notes.md
|
||
files: dist/*
|
||
generate_release_notes: true
|
||
|
||
# workflow_run / release:published are unreliable when Release itself was
|
||
# started via GITHUB_TOKEN workflow_dispatch (Auto Tag). Explicitly cascade.
|
||
#
|
||
# This job intentionally has no checkout: pass --repo so `gh` does not need a
|
||
# local .git (bare runner → "fatal: not a git repository"). Dispatch failure
|
||
# must fail this workflow so a missed sync is visible.
|
||
sync-develop:
|
||
name: Trigger sync main into develop
|
||
needs: github-release
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- name: Dispatch Sync Main Into Develop
|
||
env:
|
||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||
run: |
|
||
gh workflow run sync-main-to-develop.yml \
|
||
--repo "${{ github.repository }}" \
|
||
--ref main \
|
||
-f version="${{ github.ref_name }}"
|
||
|
||
# FnOS FPK:复用本 Release 的 wheel + docker-publish 的 GHCR 镜像。
|
||
# 与 sync-develop 并行。Dispatch 失败必须让本 workflow 变红(PyPI 已发布仍如此)。
|
||
trigger-fnos:
|
||
name: Trigger FnOS FPK build
|
||
needs: github-release
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- name: Dispatch Build Octop FPK
|
||
env:
|
||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||
run: |
|
||
# --ref 用版本 tag,保证 FPK 打在与 PyPI / 镜像相同的 commit 上
|
||
gh workflow run fnos-build-fpk.yml \
|
||
--repo "${{ github.repository }}" \
|
||
--ref "${{ github.ref_name }}"
|