Files
trycua--cua/.github/workflows/release-github-reusable.yml
wehub-resource-sync 91e75e620b
CI: cua-driver distro-compat matrix / debian:12 (glibc 2.36) (push) Has been cancelled
CI: SPDX Headers / Check SPDX headers (warn-only) (push) Has been cancelled
CD: Docs MCP Server / build (linux/amd64) (push) Has been cancelled
CD: Docs MCP Server / build (linux/arm64) (push) Has been cancelled
CD: Docs MCP Server / merge (push) Has been cancelled
CI: cua-driver distro-compat matrix / Resolve release version (push) Has been cancelled
CI: cua-driver distro-compat matrix / fedora:41 (glibc 2.40) (push) Has been cancelled
CI: cua-driver distro-compat matrix / rockylinux:9 (glibc 2.34) (push) Has been cancelled
CI: cua-driver distro-compat matrix / ubuntu:22.04 (glibc 2.35) (push) Has been cancelled
CI: cua-driver distro-compat matrix / ubuntu:24.04 (glibc 2.39) (push) Has been cancelled
CI: cua-driver distro-compat matrix / Distro compat summary (push) Has been cancelled
CI: Rust Linux unit / Rust Linux unit and compile (push) Has been cancelled
CI: Rust Windows unit / Rust Windows unit and compile (push) Has been cancelled
CI: Nix Linux Rust source / Nix / compositor build (push) Has been cancelled
CI: Nix Linux Rust source / Nix / driver package (push) Has been cancelled
CI: Nix Linux Rust source / Nix / Rust unit tests (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:03:19 +08:00

182 lines
6.3 KiB
YAML

name: Reusable GitHub Release Workflow
on:
workflow_call:
inputs:
tag_name:
description: "Git tag name (e.g., computer-v0.5.0)"
required: true
type: string
release_name:
description: "Release display name (e.g., cua-computer v0.5.0)"
required: true
type: string
module_path:
description: "Path to the module for filtering commits (e.g., libs/python/agent)"
required: false
type: string
default: ""
generate_notes:
description: "Auto-generate release notes with attribution"
required: false
type: boolean
default: true
body:
description: "Custom release notes content (appended to auto-generated notes)"
required: false
type: string
default: ""
attach_artifacts:
description: "Whether to download and attach workflow artifacts to the release"
required: false
type: boolean
default: false
draft:
description: "Create as draft release"
required: false
type: boolean
default: false
prerelease:
description: "Mark as pre-release"
required: false
type: boolean
default: false
permissions:
contents: write
jobs:
create-release:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate path-filtered release notes
if: inputs.module_path != '' && inputs.generate_notes
id: release-notes
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Extract tag prefix to find previous release (e.g., "pypi-agent-v" from "pypi-agent-v0.5.0")
TAG_PREFIX=$(echo "${{ inputs.tag_name }}" | sed 's/[0-9]*\.[0-9]*\.[0-9]*$//')
# Find previous tag with same prefix
PREV_TAG=$(git tag -l "${TAG_PREFIX}*" --sort=-v:refname | grep -v "^${{ inputs.tag_name }}$" | head -n 1 || echo "")
echo "Current tag: ${{ inputs.tag_name }}"
echo "Tag prefix: $TAG_PREFIX"
echo "Previous tag: $PREV_TAG"
# Generate release notes with GitHub username attribution
NOTES=""
if [ -n "$PREV_TAG" ]; then
echo "Generating notes for commits between $PREV_TAG and HEAD in ${{ inputs.module_path }}"
COMMIT_RANGE="${PREV_TAG}..HEAD"
else
echo "No previous tag found, generating notes for all commits in ${{ inputs.module_path }}"
COMMIT_RANGE="HEAD"
fi
# Get commits and process each one to fetch GitHub username
while IFS='|' read -r sha subject; do
# Skip automated bump commits (e.g., "Bump cua-agent to v0.7.22")
if [[ "$subject" =~ ^Bump\ cua- ]]; then
continue
fi
# Try to get GitHub username via API
USERNAME=$(gh api repos/${{ github.repository }}/commits/${sha} --jq '.author.login' 2>/dev/null || echo "")
# If API call fails or no author found (empty or "null"), fall back to commit author email
if [ -z "$USERNAME" ] || [ "$USERNAME" = "null" ]; then
AUTHOR_EMAIL=$(git show -s --format='%ae' ${sha})
# Try to extract username from GitHub noreply email format
if [[ "$AUTHOR_EMAIL" =~ ^([0-9]+\+)?([^@]+)@users\.noreply\.github\.com$ ]]; then
USERNAME="${BASH_REMATCH[2]}"
else
# Last resort: use author name without @ symbol
USERNAME=$(git show -s --format='%an' ${sha})
fi
fi
# Link PR numbers: (#123) -> ([#123](https://github.com/REPO/pull/123))
LINKED_SUBJECT=$(echo "$subject" | sed 's~(#\([0-9]*\))~([#\1](https://github.com/${{ github.repository }}/pull/\1))~g')
SHORT_SHA=$(echo ${sha} | cut -c1-7)
NOTES="${NOTES}* ${LINKED_SUBJECT} (${SHORT_SHA}) by @${USERNAME}"$'\n'
done < <(git log ${COMMIT_RANGE} --pretty=format:"%H|%s" -- "${{ inputs.module_path }}" | head -50)
if [ -z "$NOTES" ]; then
NOTES="Maintenance release — dependency updates only."
fi
# Store notes in output (handle multiline)
echo "RELEASE_NOTES<<EOF" >> $GITHUB_OUTPUT
echo "## What's Changed" >> $GITHUB_OUTPUT
echo "" >> $GITHUB_OUTPUT
echo "$NOTES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Download artifacts
if: inputs.attach_artifacts
uses: actions/download-artifact@v4
with:
path: release-assets
merge-multiple: true
- name: List downloaded artifacts
if: inputs.attach_artifacts
run: |
echo "Downloaded artifacts:"
ls -lah release-assets/
- name: Prepare release body
id: prepare-body
env:
# Use env vars to avoid shell interpretation of backticks in commit messages
RELEASE_NOTES: ${{ steps.release-notes.outputs.RELEASE_NOTES }}
CUSTOM_BODY: ${{ inputs.body }}
run: |
# Combine path-filtered notes with custom body
BODY=""
# Add path-filtered notes if available
if [ -n "$RELEASE_NOTES" ]; then
BODY="$RELEASE_NOTES"
fi
# Add custom body if provided
if [ -n "$CUSTOM_BODY" ]; then
if [ -n "$BODY" ]; then
BODY="$BODY
$CUSTOM_BODY"
else
BODY="$CUSTOM_BODY"
fi
fi
# Store in output
echo "BODY<<EOF" >> $GITHUB_OUTPUT
echo "$BODY" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Create Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ inputs.tag_name }}
name: ${{ inputs.release_name }}
body: ${{ steps.prepare-body.outputs.BODY }}
draft: ${{ inputs.draft }}
prerelease: ${{ inputs.prerelease }}
# Only use GitHub auto-generated notes if module_path is not specified
generate_release_notes: ${{ inputs.module_path == '' && inputs.generate_notes }}
files: |
release-assets/*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}