mirror of
https://github.com/NVIDIA/OpenShell.git
synced 2026-10-29 07:23:25 +08:00
* ci(release): infer optional workflow tags Signed-off-by: Simon Scatton <sscatton@nvidia.com> * fix(release): use resolved tag in success notifications Signed-off-by: Simon Scatton <sscatton@nvidia.com> * fix(release): pin prerelease notes to resolved candidate Signed-off-by: Simon Scatton <sscatton@nvidia.com> --------- Signed-off-by: Simon Scatton <sscatton@nvidia.com>
229 lines
8.1 KiB
YAML
229 lines
8.1 KiB
YAML
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
name: Pre-release
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- "v*.*.*-pre.*"
|
|
workflow_dispatch:
|
|
inputs:
|
|
tag:
|
|
description: "Existing prerelease tag (e.g. v0.0.4-pre.1); omit to create the next candidate on this branch"
|
|
required: false
|
|
type: string
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
resolve:
|
|
name: Resolve Prerelease Tag
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 5
|
|
permissions:
|
|
contents: write
|
|
concurrency:
|
|
group: release-prerelease-tags
|
|
cancel-in-progress: false
|
|
queue: max
|
|
outputs:
|
|
tag: ${{ steps.tag.outputs.tag }}
|
|
source-sha: ${{ steps.tag.outputs.source_sha }}
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
fetch-depth: 0
|
|
persist-credentials: false
|
|
|
|
- uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
|
|
with:
|
|
version: "0.10.12"
|
|
python-version: "3.13"
|
|
enable-cache: false
|
|
|
|
- name: Resolve or create candidate tag
|
|
id: tag
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
RELEASE_TAG: ${{ inputs.tag }}
|
|
EVENT_NAME: ${{ github.event_name }}
|
|
REF_TYPE: ${{ github.ref_type }}
|
|
REF_NAME: ${{ github.ref_name }}
|
|
run: |
|
|
set -euo pipefail
|
|
tag="${RELEASE_TAG}"
|
|
if [[ "${EVENT_NAME}" == "push" ]]; then
|
|
tag="${REF_NAME}"
|
|
fi
|
|
if [[ -z "${tag}" ]]; then
|
|
test "${REF_TYPE}" = branch
|
|
tag=$(uv run --no-project python tasks/scripts/next-prerelease-tag.py)
|
|
source_sha=$(git rev-parse HEAD)
|
|
gh api --method POST "repos/${GITHUB_REPOSITORY}/git/refs" \
|
|
-f "ref=refs/tags/${tag}" -f "sha=${source_sha}"
|
|
else
|
|
if [[ ! "${tag}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+-pre\.[1-9][0-9]*$ ]]; then
|
|
echo "Unsupported prerelease tag: ${tag}" >&2
|
|
exit 1
|
|
fi
|
|
source_sha=$(git rev-parse "refs/tags/${tag}^{commit}")
|
|
fi
|
|
{
|
|
echo "tag=${tag}"
|
|
echo "source_sha=${source_sha}"
|
|
} >> "${GITHUB_OUTPUT}"
|
|
{
|
|
echo "## Prerelease candidate"
|
|
echo "- Tag: \`${tag}\`"
|
|
echo "- Source commit: \`${source_sha}\`"
|
|
} >> "${GITHUB_STEP_SUMMARY}"
|
|
|
|
build:
|
|
name: Build
|
|
needs: resolve
|
|
permissions:
|
|
actions: read
|
|
contents: read
|
|
packages: write
|
|
uses: ./.github/workflows/release-build.yml
|
|
with:
|
|
release-tag: ${{ needs.resolve.outputs.tag }}
|
|
expected-source-sha: ${{ needs.resolve.outputs.source-sha }}
|
|
is-prerelease: true
|
|
secrets:
|
|
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
|
|
release-notes:
|
|
name: Preview Release Notes
|
|
needs: [resolve, build]
|
|
permissions:
|
|
contents: read
|
|
pull-requests: read
|
|
uses: ./.github/workflows/release-notes.yml
|
|
with:
|
|
release-tag: ${{ needs.resolve.outputs.tag }}
|
|
advisory: true
|
|
secrets:
|
|
LLM_INFERENCE_API_KEY: ${{ secrets.LLM_INFERENCE_API_KEY }}
|
|
|
|
publish:
|
|
name: Publish
|
|
needs: [resolve, build]
|
|
permissions:
|
|
actions: read
|
|
contents: write
|
|
pull-requests: read
|
|
packages: write
|
|
id-token: write
|
|
attestations: write
|
|
artifact-metadata: write
|
|
uses: ./.github/workflows/release-publish.yml
|
|
with:
|
|
release-tag: ${{ needs.resolve.outputs.tag }}
|
|
source-sha: ${{ needs.build.outputs.source_sha }}
|
|
semver: ${{ needs.build.outputs.semver }}
|
|
python-version: ${{ needs.build.outputs.python_version }}
|
|
npm-version: ${{ needs.build.outputs.npm_version }}
|
|
is-prerelease: true
|
|
secrets:
|
|
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_STORE_CREDENTIALS }}
|
|
|
|
qualify:
|
|
name: Qualify
|
|
needs: [resolve, build]
|
|
permissions:
|
|
actions: read
|
|
contents: read
|
|
packages: write
|
|
security-events: write
|
|
pull-requests: read
|
|
uses: ./.github/workflows/release-qualification.yml
|
|
with:
|
|
release-tag: ${{ needs.resolve.outputs.tag }}
|
|
source-sha: ${{ needs.build.outputs.source_sha }}
|
|
is-prerelease: true
|
|
secrets:
|
|
CODEX_SECURITY_API_KEY: ${{ secrets.CODEX_SECURITY_API_KEY }}
|
|
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
|
|
notify-prerelease-success:
|
|
name: Notify Prerelease Success
|
|
needs: [resolve, build, publish, qualify]
|
|
if: success()
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 2
|
|
permissions: {}
|
|
steps:
|
|
- name: Send Slack notification
|
|
continue-on-error: true
|
|
env:
|
|
RELEASE_TAG: ${{ needs.resolve.outputs.tag }}
|
|
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_OPENSHELL_TRIAGE_WEBHOOK_URL }}
|
|
RUN_URL: ${{ format('{0}/{1}/actions/runs/{2}/attempts/{3}', github.server_url, github.repository, github.run_id, github.run_attempt) }}
|
|
TAG_URL: ${{ format('{0}/{1}/tree/{2}', github.server_url, github.repository, needs.resolve.outputs.tag) }}
|
|
run: |
|
|
set -euo pipefail
|
|
if [[ -z "${SLACK_WEBHOOK_URL}" ]]; then
|
|
echo "::notice::SLACK_OPENSHELL_TRIAGE_WEBHOOK_URL is unset; skipping Slack notification."
|
|
exit 0
|
|
fi
|
|
|
|
jq -n --arg tag "${RELEASE_TAG}" --arg tag_url "${TAG_URL}" \
|
|
--arg attempt "${GITHUB_RUN_ATTEMPT}" --arg run_url "${RUN_URL}" \
|
|
'{text: (":white_check_mark: OpenShell prerelease <" + $tag_url + "|" + $tag + "> succeeded (attempt " + $attempt + ").\n<" + $run_url + "|View release run and artifacts>"), unfurl_links: false, unfurl_media: false}' |
|
|
curl --fail --silent --show-error --connect-timeout 5 --max-time 15 \
|
|
--header 'Content-Type: application/json' --data-binary @- "${SLACK_WEBHOOK_URL}"
|
|
|
|
notify-prerelease-failure:
|
|
name: Notify Prerelease Failure
|
|
needs: [resolve, build, publish, qualify]
|
|
if: failure()
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 2
|
|
permissions:
|
|
actions: read
|
|
defaults:
|
|
run:
|
|
shell: bash
|
|
steps:
|
|
- name: Send Slack notification
|
|
continue-on-error: true
|
|
env:
|
|
RELEASE_TAG: ${{ needs.resolve.outputs.tag || inputs.tag || github.ref_name }}
|
|
PUBLICATION_RESULT: ${{ needs.publish.result }}
|
|
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_OPENSHELL_TRIAGE_WEBHOOK_URL }}
|
|
SLACK_MENTION: ${{ secrets.SLACK_OPENSHELL_TRIAGE_MENTION }}
|
|
GH_TOKEN: ${{ github.token }}
|
|
RUN_URL: ${{ format('{0}/{1}/actions/runs/{2}/attempts/{3}', github.server_url, github.repository, github.run_id, github.run_attempt) }}
|
|
run: |
|
|
set -euo pipefail
|
|
if [[ -z "${SLACK_WEBHOOK_URL}" ]]; then
|
|
echo "::notice::SLACK_OPENSHELL_TRIAGE_WEBHOOK_URL is unset; skipping Slack notification."
|
|
exit 0
|
|
fi
|
|
|
|
message=":x: OpenShell prerelease ${RELEASE_TAG} failed (attempt ${GITHUB_RUN_ATTEMPT})."
|
|
if [[ "${PUBLICATION_RESULT}" == "success" ]]; then
|
|
message+=" Published artifacts remain available."
|
|
fi
|
|
if [[ -n "${SLACK_MENTION}" ]]; then
|
|
message+=" ${SLACK_MENTION}"
|
|
fi
|
|
|
|
failed_jobs=$(gh api --paginate \
|
|
"repos/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}/attempts/${GITHUB_RUN_ATTEMPT}/jobs?per_page=100" \
|
|
--jq '.jobs[] | select(.conclusion == "failure" or .conclusion == "timed_out") | "• <\(.html_url)|\(.name)>"') || {
|
|
echo "::warning::Could not list failed jobs; sending the notification without them."
|
|
failed_jobs=""
|
|
}
|
|
if [[ -n "${failed_jobs}" ]]; then
|
|
message+=$'\n\nFailed jobs\n'"${failed_jobs}"
|
|
fi
|
|
|
|
jq -n --arg text "${message}" --arg run_url "${RUN_URL}" \
|
|
'{text: ($text + "\n<" + $run_url + "|View failed release run>"), unfurl_links: false, unfurl_media: false}' |
|
|
curl --fail --silent --show-error --connect-timeout 5 --max-time 15 \
|
|
--header 'Content-Type: application/json' --data-binary @- "${SLACK_WEBHOOK_URL}"
|