mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-03 03:03:24 -04:00
- Add testing-strategy.yml that calls existing ci.yml + adds macOS/smoke for stable - Add promote-branch.yml for develop alpha beta main promotion PRs - Add deployment-strategy.yml for npm (alpha/beta/latest) + Docker (GHCR) - Add release-orchestrator.yml to coordinate version changelog test deploy - Add version-operations.yml for YYYY.M.D versioning with prerelease suffixes - Add generate-changelog.yml for conventional commit parsing - Add release.yml manual trigger workflow - Add discord-notify composite action for notifications - Modify ci.yml to support workflow_call for reuse by testing-strategy
214 lines
6.7 KiB
YAML
214 lines
6.7 KiB
YAML
name: Release Orchestrator
|
|
|
|
# Orchestrates staged releases for openclaw
|
|
#
|
|
# This workflow is called when code is promoted to main (stable release)
|
|
# or can be triggered manually for alpha/beta releases from their branches.
|
|
#
|
|
# Flow: version → changelog → test → deploy → release
|
|
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
release_type:
|
|
description: 'Release type: alpha, beta, or stable'
|
|
required: true
|
|
type: string
|
|
source_branch:
|
|
description: 'Source branch for the release'
|
|
required: true
|
|
type: string
|
|
dry_run:
|
|
description: 'Perform a dry run without publishing'
|
|
required: false
|
|
type: boolean
|
|
default: false
|
|
outputs:
|
|
version:
|
|
description: 'The released version'
|
|
value: ${{ jobs.version.outputs.new_version }}
|
|
release_url:
|
|
description: 'URL to the GitHub release'
|
|
value: ${{ jobs.release.outputs.release_url }}
|
|
status:
|
|
description: 'Release status'
|
|
value: ${{ jobs.release.outputs.status }}
|
|
secrets:
|
|
NPM_TOKEN:
|
|
required: false
|
|
DISCORD_WEBHOOK_URL:
|
|
required: false
|
|
|
|
jobs:
|
|
# Get commits since last release
|
|
get-commits:
|
|
name: Get Commits
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
commits: ${{ steps.commits.outputs.commits }}
|
|
has_changes: ${{ steps.commits.outputs.has_changes }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
ref: ${{ inputs.source_branch }}
|
|
|
|
- name: Get commits since last tag
|
|
id: commits
|
|
run: |
|
|
# Get latest tag for this release type
|
|
case "${{ inputs.release_type }}" in
|
|
alpha)
|
|
PATTERN="v*-alpha.*"
|
|
;;
|
|
beta)
|
|
PATTERN="v*-beta.*"
|
|
;;
|
|
stable)
|
|
PATTERN="v[0-9]*.[0-9]*.[0-9]*"
|
|
;;
|
|
esac
|
|
|
|
LATEST_TAG=$(git tag -l "$PATTERN" --sort=-v:refname | head -1)
|
|
|
|
if [ -z "$LATEST_TAG" ]; then
|
|
# No previous tag, use all commits
|
|
LATEST_TAG=$(git rev-list --max-parents=0 HEAD)
|
|
echo "No previous ${{ inputs.release_type }} tag found, using initial commit"
|
|
else
|
|
echo "Latest ${{ inputs.release_type }} tag: $LATEST_TAG"
|
|
fi
|
|
|
|
COMMITS=$(git log ${LATEST_TAG}..HEAD --oneline --format="- %s (%h)")
|
|
|
|
if [ -z "$COMMITS" ]; then
|
|
echo "has_changes=false" >> $GITHUB_OUTPUT
|
|
echo "commits=" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "has_changes=true" >> $GITHUB_OUTPUT
|
|
echo "commits<<EOF" >> $GITHUB_OUTPUT
|
|
echo "$COMMITS" >> $GITHUB_OUTPUT
|
|
echo "EOF" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
# Version operations
|
|
version:
|
|
name: Version
|
|
needs: get-commits
|
|
if: needs.get-commits.outputs.has_changes == 'true'
|
|
uses: ./.github/workflows/version-operations.yml
|
|
with:
|
|
release_type: ${{ inputs.release_type }}
|
|
source_branch: ${{ inputs.source_branch }}
|
|
should_bump: true
|
|
dry_run: ${{ inputs.dry_run }}
|
|
|
|
# Generate changelog
|
|
changelog:
|
|
name: Changelog
|
|
needs: [get-commits, version]
|
|
uses: ./.github/workflows/generate-changelog.yml
|
|
with:
|
|
version: ${{ needs.version.outputs.new_version }}
|
|
commits: ${{ needs.get-commits.outputs.commits }}
|
|
release_type: ${{ inputs.release_type }}
|
|
|
|
# Run full test suite for the release type
|
|
test:
|
|
name: Test
|
|
needs: version
|
|
uses: ./.github/workflows/testing-strategy.yml
|
|
with:
|
|
test_stage: ${{ inputs.release_type == 'stable' && 'stable' || inputs.release_type }}
|
|
app_version: ${{ needs.version.outputs.new_version }}
|
|
secrets: inherit
|
|
|
|
# Deploy (npm + Docker)
|
|
deploy:
|
|
name: Deploy
|
|
needs: [version, test]
|
|
if: ${{ !inputs.dry_run && needs.test.outputs.test_status == 'passed' }}
|
|
uses: ./.github/workflows/deployment-strategy.yml
|
|
with:
|
|
deployment_stage: ${{ inputs.release_type }}
|
|
app_version: ${{ needs.version.outputs.new_version }}
|
|
source_branch: ${{ inputs.source_branch }}
|
|
secrets: inherit
|
|
|
|
# Create GitHub release
|
|
release:
|
|
name: GitHub Release
|
|
needs: [version, changelog, deploy]
|
|
if: ${{ !inputs.dry_run }}
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
release_url: ${{ steps.create-release.outputs.html_url }}
|
|
status: ${{ steps.status.outputs.status }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
ref: ${{ inputs.source_branch }}
|
|
|
|
- name: Create GitHub Release
|
|
id: create-release
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
tag_name: v${{ needs.version.outputs.new_version }}
|
|
name: openclaw ${{ needs.version.outputs.new_version }}
|
|
body: ${{ needs.changelog.outputs.changelog }}
|
|
prerelease: ${{ inputs.release_type != 'stable' }}
|
|
draft: false
|
|
|
|
- name: Set status
|
|
id: status
|
|
run: echo "status=success" >> $GITHUB_OUTPUT
|
|
|
|
# Notify on success
|
|
notify-success:
|
|
name: Notify Success
|
|
needs: [version, release]
|
|
if: ${{ always() && needs.release.result == 'success' }}
|
|
runs-on: ubuntu-latest
|
|
env:
|
|
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Discord notification
|
|
if: env.DISCORD_WEBHOOK_URL != ''
|
|
uses: ./.github/actions/discord-notify
|
|
with:
|
|
webhook_url: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
|
title: '🎉 Released: openclaw v${{ needs.version.outputs.new_version }}'
|
|
description: |
|
|
**Type**: ${{ inputs.release_type }}
|
|
**Release**: ${{ needs.release.outputs.release_url }}
|
|
color: '3066993'
|
|
|
|
# Notify on failure
|
|
notify-failure:
|
|
name: Notify Failure
|
|
needs: [version, test, deploy, release]
|
|
if: ${{ always() && (needs.test.outputs.test_status != 'passed' || needs.deploy.result == 'failure' || needs.release.result == 'failure') }}
|
|
runs-on: ubuntu-latest
|
|
env:
|
|
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Discord notification
|
|
if: env.DISCORD_WEBHOOK_URL != ''
|
|
uses: ./.github/actions/discord-notify
|
|
with:
|
|
webhook_url: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
|
title: '❌ Release Failed: ${{ inputs.release_type }}'
|
|
description: |
|
|
**Branch**: ${{ inputs.source_branch }}
|
|
**Tests**: ${{ needs.test.outputs.test_status }}
|
|
[View Logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
|
|
color: '15158332'
|