Files
2026-07-13 13:12:00 +08:00

77 lines
3.7 KiB
YAML

# Create a GitHub Release entry (the `…/releases` page) when a version tag is
# pushed. This is METADATA ONLY — it does NOT build or publish any installable
# artifact. PyPI publishing lives in the central secure-release repo
# (databricks/secure-public-registry-releases-eng → `omnigent` workflow), on
# hardened runners with OIDC Trusted Publishing and a mandatory dependency
# scan. Keeping those concerns separate is deliberate (see RELEASING.md):
#
# * This job runs NO project or third-party code — no build, no `pip
# install`/`npm ci`, no tests. Its only action is SHA-pinned
# `actions/checkout` plus `gh release create`. A malicious tagged commit
# therefore cannot execute anything here.
# * It uses the ephemeral `GITHUB_TOKEN` (no stored secret / PAT). The single
# elevated scope, `contents: write`, is the minimum GitHub requires to
# create a release and nothing else in the job uses it.
# * It attaches NO wheels. The release carries only a placeholder body and the
# source tarball GitHub auto-attaches, so PyPI (the scanned, securely
# published channel) stays the single source of installable artifacts.
# * The body is a short placeholder — the curated notes are filled in by
# `draft-release-notes.yml` (which fires after this on `workflow_run`). We do
# NOT use `--generate-notes`: we write our own notes, and for a large
# PR range GitHub's auto-notes overflow the 125k release-body limit.
# * The release is created as a DRAFT: a human verifies/edits the drafted
# notes and publishes it (ideally after the prod PyPI publish lands), so a
# bot never makes a public release on its own.
name: GitHub Release
on:
push:
tags:
# Version tags only (v0.2.0, v0.2.0rc1, …) — `v[0-9]*` avoids triggering
# on non-release tags like `v-infra-*`.
- "v[0-9]*"
# Least privilege: creating a release requires `contents: write`; nothing here
# needs anything more.
permissions:
contents: write
jobs:
draft-release:
# Inert in forks / mirrors — only the canonical repo should cut releases.
if: github.repository == 'omnigent-ai/omnigent'
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: Draft release with a placeholder body
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ github.ref_name }}
run: |
# Rerun-safe: if a release for this tag already exists (a rerun, a
# deleted-and-re-pushed tag, or a manual release), skip instead of
# failing the job. An `if` so this can't trip `set -e`.
if gh release view "$TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
echo "Release $TAG already exists — skipping." | tee -a "$GITHUB_STEP_SUMMARY"
exit 0
fi
# rc / dev / alpha / beta tags are flagged as pre-releases.
pre=""
case "$TAG" in
*rc*|*dev*|*a[0-9]*|*b[0-9]*) pre="--prerelease" ;;
esac
# $pre is intentionally UNQUOTED: it word-splits to nothing when empty,
# and is only ever "" or "--prerelease" (set just above, never from
# external input). Quoting it would pass an empty positional arg.
gh release create "$TAG" \
--repo "$GITHUB_REPOSITORY" \
--draft \
--verify-tag \
--notes "_Release notes are being drafted automatically — check back shortly._" \
--title "$TAG" \
$pre
echo "Drafted release $TAG — curated notes will be filled in by draft-release-notes.yml; review and publish from the Releases page." \
| tee -a "$GITHUB_STEP_SUMMARY"