ci : update release workflow to be consistent with llama.cpp
work in progress...
This commit is contained in:
parent
b6e63fa4ac
commit
43e5d9f257
|
|
@ -0,0 +1,87 @@
|
|||
name: Make Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
commit:
|
||||
description: 'Commit SHA to release (empty = branch HEAD)'
|
||||
required: false
|
||||
default: ''
|
||||
type: string
|
||||
dry_run:
|
||||
description: 'Dry run - validate without creating the tag'
|
||||
required: true
|
||||
type: boolean
|
||||
default: true
|
||||
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
make-release:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
|
||||
with:
|
||||
ref: ${{ inputs.commit != '' && inputs.commit || github.ref_name }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Run release checks
|
||||
id: checks
|
||||
run: bash scripts/make-release-checks.sh ${{ github.event.inputs.dry_run == 'true' && '--dry-run' || '' }}
|
||||
env:
|
||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||
RELEASE_BRANCH: ${{ github.ref_name }}
|
||||
|
||||
- name: Create release tag
|
||||
if: ${{ github.event.inputs.dry_run == 'false' }}
|
||||
run: |
|
||||
VERSION="${{ steps.checks.outputs.version }}"
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git tag -a "${VERSION}" -m "Release ${VERSION}"
|
||||
git push origin "${VERSION}"
|
||||
echo "Created and pushed tag ${VERSION}"
|
||||
|
||||
- name: Generate release description
|
||||
id: desc
|
||||
run: bash scripts/make-release-desc.sh "${{ steps.checks.outputs.version }}"
|
||||
env:
|
||||
GITHUB_REPOSITORY: ${{ github.repository }}
|
||||
|
||||
- name: Create release
|
||||
if: ${{ github.event.inputs.dry_run == 'false' }}
|
||||
uses: ggml-org/action-create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
with:
|
||||
tag_name: ${{ steps.checks.outputs.version }}
|
||||
# TODO: remove the prerelease flag once the semantic versioning workflow is ready
|
||||
# ref: https://github.com/ggml-org/ggml/discussions/1579
|
||||
prerelease: true
|
||||
body: |
|
||||
> [!NOTE]
|
||||
> Semantic versioning is still work in progress.
|
||||
> More info can be found in https://github.com/ggml-org/ggml/discussions/1579
|
||||
|
||||
${{ steps.desc.outputs.nightly }}
|
||||
|
||||
## ${{ steps.desc.outputs.changelog_title }}
|
||||
|
||||
${{ steps.desc.outputs.changelog }}
|
||||
|
||||
- name: Dry run summary
|
||||
if: ${{ github.event.inputs.dry_run == 'true' }}
|
||||
run: |
|
||||
if [[ "${{ steps.checks.outputs.checks_passed }}" == "true" ]]; then
|
||||
echo "Dry run complete - all checks passed."
|
||||
echo "Would have created tag: ${{ steps.checks.outputs.version }}"
|
||||
else
|
||||
echo "::error::Dry run found release check failures. A release tag would not be created."
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -1,10 +1,14 @@
|
|||
name: Release
|
||||
|
||||
# Builds dev releases (b* tags) when manually dispatched with create_release: true.
|
||||
# Run this as a verification build before making a release (see make-release.yml).
|
||||
# Pushing a v* tag does not trigger this workflow; releases are made via make-release.yml.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
create_release:
|
||||
description: 'Create new release'
|
||||
description: 'Create new developer release'
|
||||
required: true
|
||||
type: boolean
|
||||
pre_release_tag:
|
||||
|
|
@ -12,10 +16,6 @@ on:
|
|||
required: false
|
||||
type: string
|
||||
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
env:
|
||||
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
|
||||
VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite"
|
||||
|
|
@ -55,18 +55,10 @@ jobs:
|
|||
echo "BRANCH_NAME: ${{ env.BRANCH_NAME }}"
|
||||
echo "CUSTOM_TAG: $CUSTOM_TAG"
|
||||
|
||||
if [[ "${{ github.ref_type }}" == "tag" ]]; then
|
||||
echo "Using pushed tag name"
|
||||
TAG_NAME="${{ github.ref_name }}"
|
||||
SHOULD_RELEASE="true"
|
||||
elif [[ -n "$CUSTOM_TAG" ]]; then
|
||||
if [[ -n "$CUSTOM_TAG" ]]; then
|
||||
echo "Using custom tag"
|
||||
TAG_NAME="${CUSTOM_TAG}"
|
||||
SHOULD_RELEASE="true"
|
||||
elif [[ "${{ github.event.inputs.create_release }}" == "true" ]]; then
|
||||
echo "Manual release requested"
|
||||
SHOULD_RELEASE="true"
|
||||
TAG_NAME="b${BUILD_NUMBER}"
|
||||
elif [[ "${{ env.BRANCH_NAME }}" == "master" ]]; then
|
||||
echo "Using master branch format"
|
||||
TAG_NAME="b${BUILD_NUMBER}"
|
||||
|
|
@ -78,6 +70,11 @@ jobs:
|
|||
SHOULD_RELEASE="false"
|
||||
fi
|
||||
|
||||
if [[ "${{ github.event.inputs.create_release }}" == "true" ]]; then
|
||||
echo "Manual release requested"
|
||||
SHOULD_RELEASE="true"
|
||||
fi
|
||||
|
||||
echo "Final tag name: $TAG_NAME"
|
||||
echo "Should release: $SHOULD_RELEASE"
|
||||
echo "name=$TAG_NAME" >> $GITHUB_OUTPUT
|
||||
|
|
@ -584,7 +581,7 @@ jobs:
|
|||
name: whisper-${{ needs.determine-tag.outputs.tag_name }}-xcframework.zip
|
||||
|
||||
release:
|
||||
if: ${{ github.event.inputs.create_release == 'true' || github.event.inputs.pre_release_tag != '' || startsWith(github.ref, 'refs/tags/v') }}
|
||||
if: ${{ github.event.inputs.create_release == 'true' || github.event.inputs.pre_release_tag != '' }}
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
|
|
@ -620,6 +617,16 @@ jobs:
|
|||
id: move_artifacts
|
||||
run: mkdir -p ./artifact/release && mv ./artifact/*/*.zip ./artifact/release && mv ./artifact/*/*.tar.gz ./artifact/release 2>/dev/null || true
|
||||
|
||||
- name: Create and push git tag
|
||||
run: |
|
||||
TAG="${{ needs.determine-tag.outputs.tag_name }}"
|
||||
if git rev-parse -q --verify "refs/tags/${TAG}" >/dev/null 2>&1; then
|
||||
echo "Tag ${TAG} already exists, skipping creation"
|
||||
else
|
||||
git tag "${TAG}"
|
||||
git push origin "${TAG}"
|
||||
fi
|
||||
|
||||
- name: Create release
|
||||
id: create_release
|
||||
uses: ggml-org/action-create-release@v1
|
||||
|
|
@ -627,8 +634,6 @@ jobs:
|
|||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ needs.determine-tag.outputs.tag_name }}
|
||||
prerelease: ${{ github.event.inputs.pre_release_tag != '' }}
|
||||
draft: true
|
||||
|
||||
- name: Upload release
|
||||
id: upload_release
|
||||
|
|
|
|||
|
|
@ -0,0 +1,125 @@
|
|||
#!/bin/bash
|
||||
# Run all pre-release checks and determine the release version.
|
||||
#
|
||||
# Usage: make-release-checks.sh [--dry-run]
|
||||
# --dry-run: warn on failures instead of aborting
|
||||
#
|
||||
# Env (when running in GitHub Actions):
|
||||
# GH_TOKEN, GITHUB_REPOSITORY, GITHUB_OUTPUT
|
||||
# RELEASE_BRANCH: when set, HEAD must belong to origin/RELEASE_BRANCH and must
|
||||
# not be older than 3 days from the branch HEAD (skipped when unset)
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
|
||||
DRY_RUN=false
|
||||
CHECKS_PASSED=true
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--dry-run) DRY_RUN=true ;;
|
||||
*) echo "Unknown argument: $arg"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
MAJOR=$(grep "set(WHISPER_VERSION_MAJOR" "$REPO_ROOT/CMakeLists.txt" | grep -oP '\d+')
|
||||
MINOR=$(grep "set(WHISPER_VERSION_MINOR" "$REPO_ROOT/CMakeLists.txt" | grep -oP '\d+')
|
||||
PATCH=$(grep "set(WHISPER_VERSION_PATCH" "$REPO_ROOT/CMakeLists.txt" | grep -oP '\d+')
|
||||
VERSION="v${MAJOR}.${MINOR}.${PATCH}"
|
||||
echo "Determined version: ${VERSION}"
|
||||
if [[ -n "${GITHUB_OUTPUT:-}" ]]; then
|
||||
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
SHA=$(git rev-parse HEAD)
|
||||
|
||||
echo "Checking that commit ${SHA} belongs to the release branch..."
|
||||
if [[ -z "${RELEASE_BRANCH:-}" ]]; then
|
||||
echo "Warning: RELEASE_BRANCH not set - skipping commit check (local run)"
|
||||
else
|
||||
TIP="origin/${RELEASE_BRANCH}"
|
||||
COMMIT_ERR=""
|
||||
if ! git rev-parse --verify "${TIP}" >/dev/null 2>&1; then
|
||||
COMMIT_ERR="branch ${RELEASE_BRANCH} not found on remote"
|
||||
elif ! git merge-base --is-ancestor "${SHA}" "${TIP}"; then
|
||||
COMMIT_ERR="commit ${SHA} is not part of branch ${RELEASE_BRANCH}"
|
||||
else
|
||||
COMMIT_TS=$(git show -s --format=%ct "${SHA}")
|
||||
TIP_TS=$(git show -s --format=%ct "${TIP}")
|
||||
AGE_DAYS=$(( (TIP_TS - COMMIT_TS) / 86400 ))
|
||||
if (( TIP_TS - COMMIT_TS > 3 * 86400 )); then
|
||||
COMMIT_ERR="commit ${SHA} is ${AGE_DAYS} day(s) older than the HEAD of ${RELEASE_BRANCH} (max: 3)"
|
||||
fi
|
||||
fi
|
||||
if [[ -n "${COMMIT_ERR}" ]]; then
|
||||
if [[ "$DRY_RUN" == "true" ]]; then
|
||||
echo "Warning: ${COMMIT_ERR} (dry run, continuing)."
|
||||
CHECKS_PASSED=false
|
||||
else
|
||||
echo "Error: ${COMMIT_ERR}"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Commit ${SHA} is on branch ${RELEASE_BRANCH} and within 3 days of its HEAD - OK"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Checking that tag ${VERSION} does not already exist..."
|
||||
if git ls-remote --tags origin "${VERSION}" | grep -q "${VERSION}"; then
|
||||
echo "Error: tag ${VERSION} already exists on remote"
|
||||
exit 1
|
||||
fi
|
||||
echo "Tag ${VERSION} does not exist on remote - OK"
|
||||
|
||||
echo "Checking release.yml status for commit ${SHA}..."
|
||||
if [[ -z "${GITHUB_REPOSITORY:-}" ]]; then
|
||||
echo "Warning: GITHUB_REPOSITORY not set - skipping CI check (local run)"
|
||||
else
|
||||
RUNS=$(gh api "repos/${GITHUB_REPOSITORY}/actions/workflows/release.yml/runs?per_page=100" \
|
||||
--jq "[.workflow_runs[] | select(.head_sha == \"${SHA}\" and .conclusion == \"success\")] | length")
|
||||
if [[ "$RUNS" -eq 0 ]]; then
|
||||
if [[ "$DRY_RUN" == "true" ]]; then
|
||||
echo "Warning: no successful release.yml run found for HEAD (${SHA}) (dry run, continuing)."
|
||||
CHECKS_PASSED=false
|
||||
else
|
||||
echo "Error: no successful release.yml run found for HEAD (${SHA})"
|
||||
echo "The nightly build must complete successfully before making a release."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Found successful release.yml run for HEAD."
|
||||
fi
|
||||
fi
|
||||
|
||||
MAJOR=$(grep "set(GGML_VERSION_MAJOR" "$REPO_ROOT/ggml/CMakeLists.txt" | grep -oP '\d+')
|
||||
MINOR=$(grep "set(GGML_VERSION_MINOR" "$REPO_ROOT/ggml/CMakeLists.txt" | grep -oP '\d+')
|
||||
PATCH=$(grep "set(GGML_VERSION_PATCH" "$REPO_ROOT/ggml/CMakeLists.txt" | grep -oP '\d+')
|
||||
GGML_VERSION="v${MAJOR}.${MINOR}.${PATCH}"
|
||||
echo "Local ggml version: ${GGML_VERSION}"
|
||||
|
||||
if ! git clone --depth 1 --branch "${GGML_VERSION}" https://github.com/ggml-org/ggml.git upstream-ggml 2>/dev/null; then
|
||||
echo "Warning: tag ${GGML_VERSION} not found in upstream ggml - skipping comparison"
|
||||
else
|
||||
echo "Comparing local ggml/ src and include with upstream ${GGML_VERSION}..."
|
||||
DIFF=$(diff -rq "$REPO_ROOT/ggml/src" upstream-ggml/src 2>&1 || true)
|
||||
DIFF+=$(diff -rq "$REPO_ROOT/ggml/include" upstream-ggml/include 2>&1 || true)
|
||||
DIFF+=$(diff "$REPO_ROOT/ggml/CMakeLists.txt" upstream-ggml/CMakeLists.txt 2>&1 || true)
|
||||
rm -rf upstream-ggml
|
||||
if [[ -n "$DIFF" ]]; then
|
||||
echo "local ggml/ differs from upstream ${GGML_VERSION}:"
|
||||
echo "$DIFF"
|
||||
if [[ "$DRY_RUN" == "true" ]]; then
|
||||
echo "Warning: would abort release due to ggml mismatch (dry run, continuing)."
|
||||
CHECKS_PASSED=false
|
||||
else
|
||||
echo "Error: ggml must match upstream before making a release."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "local ggml/ matches upstream ${GGML_VERSION}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "${GITHUB_OUTPUT:-}" ]]; then
|
||||
echo "checks_passed=${CHECKS_PASSED}" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
#!/bin/bash
|
||||
# Generate the description of a release: the previous release version, the
|
||||
# change log and the link to the nightly release corresponding to the commit being released.
|
||||
#
|
||||
# Usage: make-release-desc.sh <version>
|
||||
# <version>: current release version (v<maj>.<min>.<pat>, the leading v is optional)
|
||||
#
|
||||
# The previous version is the highest plain semver tag (v<maj>.<min>.<pat>)
|
||||
# strictly below <version>. The change log lists all commits between the
|
||||
# previous version tag and the release commit, one line per commit.
|
||||
#
|
||||
# The release commit is the commit <version> points at when the tag exists,
|
||||
# HEAD otherwise. The nightly release is the b* tag pointing at that commit
|
||||
# (release.yml tags the same commit); the link is only generated when that
|
||||
# tag exists.
|
||||
#
|
||||
# Env (when running in GitHub Actions):
|
||||
# GITHUB_OUTPUT: previous_tag, changelog_title, changelog and nightly are written here
|
||||
# GITHUB_REPOSITORY: owner/repo, used to build the nightly release URL (skipped when unset)
|
||||
set -euo pipefail
|
||||
|
||||
if [[ $# -ne 1 ]]; then
|
||||
echo "Usage: $(basename "$0") <version>"
|
||||
exit 1
|
||||
fi
|
||||
VERSION="$1"
|
||||
|
||||
# Accept the version with or without the leading v, reject anything else
|
||||
if [[ "${VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
VERSION="v${VERSION}"
|
||||
elif [[ ! "${VERSION}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "Error: invalid version '${VERSION}' (expected v<maj>.<min>.<pat>)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Make sure all remote tags are available locally (skipped on local runs without origin)
|
||||
if ! git fetch --tags origin 2>/dev/null; then
|
||||
echo "Warning: could not fetch tags from origin (local run?)"
|
||||
fi
|
||||
|
||||
# Release commit: the commit <version> points at when the tag exists, HEAD otherwise.
|
||||
if ! RELEASE_COMMIT="$(git rev-parse -q --verify "refs/tags/${VERSION}^{commit}" 2>/dev/null)"; then
|
||||
RELEASE_COMMIT="$(git rev-parse HEAD)"
|
||||
fi
|
||||
|
||||
echo "Release commit: $(git rev-parse --short "${RELEASE_COMMIT}")"
|
||||
|
||||
PREV="$( { git tag --list; echo "${VERSION}"; } \
|
||||
| grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' \
|
||||
| sort -V \
|
||||
| awk -v cur="${VERSION}" '$0 == cur { exit } { prev = $0 } END { print prev }')"
|
||||
|
||||
if [[ -n "${PREV}" ]]; then
|
||||
CHANGELOG="$(git log --oneline "${PREV}..${RELEASE_COMMIT}")"
|
||||
CHANGELOG_TITLE="Change log since ${PREV}"
|
||||
else
|
||||
CHANGELOG="(no previous release tag found)"
|
||||
CHANGELOG_TITLE="Change log"
|
||||
fi
|
||||
|
||||
# Nightly release: the b* tag pointing at the release commit (|| true: no match is not an error)
|
||||
NIGHTLY_TAG="$(git tag --points-at "${RELEASE_COMMIT}" | grep -E '(^|-)b[0-9]+(-[0-9a-f]{7})?$' | head -n 1 || true)"
|
||||
|
||||
NIGHTLY=""
|
||||
if [[ -n "${NIGHTLY_TAG}" ]]; then
|
||||
if [[ -n "${GITHUB_REPOSITORY:-}" ]]; then
|
||||
NIGHTLY_URL="https://github.com/${GITHUB_REPOSITORY}/releases/tag/${NIGHTLY_TAG}"
|
||||
NIGHTLY="**Nightly build:** [${NIGHTLY_TAG}](${NIGHTLY_URL})"
|
||||
echo "Nightly release: ${NIGHTLY_URL}"
|
||||
fi
|
||||
else
|
||||
echo "No nightly release found for commit $(git rev-parse --short "${RELEASE_COMMIT}")"
|
||||
fi
|
||||
|
||||
echo "Previous version: ${PREV:-none}"
|
||||
echo "${CHANGELOG}"
|
||||
|
||||
if [[ -n "${GITHUB_OUTPUT:-}" ]]; then
|
||||
{
|
||||
echo "previous_tag=${PREV}"
|
||||
echo "changelog_title=${CHANGELOG_TITLE}"
|
||||
echo "nightly=${NIGHTLY}"
|
||||
echo "changelog<<CHANGELOG_EOF"
|
||||
echo "${CHANGELOG}"
|
||||
echo "CHANGELOG_EOF"
|
||||
} >> "${GITHUB_OUTPUT}"
|
||||
fi
|
||||
Loading…
Reference in New Issue