mirror of
https://github.com/aphrody-labs/uv.git
synced 2026-10-14 14:09:09 +00:00
On top of #21447, give original build outputs and completed release artifacts distinct names. Assemble every target into one release set, using signed macOS and Windows replacements and copying Linux artifacts and sdists unchanged. Publication downloads the complete release artifacts by explicit ID. Python publication uploads the assembled wheels and sdists; GitHub publication uses cargo-dist's asset list. Distribution filenames and release URLs are unchanged. The flow is: ```text cargo-dist plan → dist-manifest-plan-<r> build-release-binaries ├── build-wheels-<package>-<target> ├── build-sdist-<package> └── build-github-archives-<target> └── SBOM inspection prepare signing inputs from the original distributions ├── signing-assembly-inputs-<r> (all original distributions) └── unsigned-binaries-<system>-<r> └── sign and notarize └── signed-binaries-<system>-<r> assemble original distributions and signed replacements ├── signed-wheels-<system>-<r> (native verification) ├── release-wheels-<package>-<r> (all targets) ├── release-sdist-<package>-<r> └── release-github-archives-<r> (all targets) native verification succeeds └── cargo-dist: local manifest, installers, checksums ├── dist-manifest-local-<r> ├── release-github-global-<r> ├── dist-manifest-global-<r> └── host: release-github-manifest-<r> ├── Python publication: exact wheel and sdist IDs └── GitHub publication: exact IDs and manifest asset list └── mirror: same artifact IDs, existing R2 file filters ``` Here `<package>` is `uv` or `uv_build`, `<system>` is `macos` or `windows`, and `<r>` is `<run-id>-<run-attempt>`. The names below are relative to #21447: | Previous name | New name | | --- | --- | | `wheels_<package>-<target>` | `build-wheels-<package>-<target>` | | `wheels_<package>-sdist` | `build-sdist-<package>` | | `artifacts-<target>` | `build-github-archives-<target>` | | `unsigned-<system>-<r>` | `unsigned-binaries-<system>-<r>` | | `signing-assembly-<r>` | `signing-assembly-inputs-<r>` | | `signed-<system>-<r>` | `signed-binaries-<system>-<r>` | | `signed-<system>-wheels-<r>` | `signed-wheels-<system>-<r>` | | `signed-uv-wheels-<r>`, `signed-uv-build-wheels-<r>` | `release-wheels-<package>-<r>`; now includes every target | | No assembled sdist artifact | `release-sdist-<package>-<r>` | | `signed-github-release-archives-<r>` | `release-github-archives-<r>`; now includes every target | | `artifacts-plan-dist-manifest` | `dist-manifest-plan-<r>` | | `artifacts-build-local-manifest` | `dist-manifest-local-<r>` | | `artifacts-build-global` | `release-github-global-<r>` and `dist-manifest-global-<r>` | | `artifacts-dist-manifest` | `release-github-manifest-<r>` | The intermediate cargo-dist manifests stay separate from publication files. The manual release helper selects the three GitHub artifacts associated with the latest hosted manifest, allowing successful producer jobs to come from earlier attempts, and publishes only the manifest's asset list. --------- Co-authored-by: Zanie Blue <contact@zanie.dev>
89 lines
2.7 KiB
Bash
Executable File
89 lines
2.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# Manually perform a GitHub release for a broken automated release that otherwise went out.
|
|
#
|
|
# PLEASE USE WITH CAUTION.
|
|
#
|
|
# It can take a while to download all the artifacts.
|
|
#
|
|
# Requires `gh` and `jq`.
|
|
|
|
set -euo pipefail
|
|
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
|
|
|
|
if [ -z "${COMMIT:-}" ]; then
|
|
echo "COMMIT is required."
|
|
exit 1
|
|
fi
|
|
|
|
if [ -z "${RUN_ID:-}" ]; then
|
|
echo "RUN_ID is required."
|
|
exit 1
|
|
fi
|
|
|
|
# Create directory for artifacts
|
|
mkdir -p "release_$RUN_ID"
|
|
cd "release_$RUN_ID"
|
|
|
|
REPO=$(gh repo view --json nameWithOwner | jq .nameWithOwner -r)
|
|
|
|
# Find the publication artifacts across all attempts of this run.
|
|
gh api --paginate "repos/$REPO/actions/runs/$RUN_ID/artifacts?per_page=100" |
|
|
jq -s '[.[].artifacts[]]' > workflow-artifacts.json
|
|
RUN_ATTEMPT=$(gh run view "$RUN_ID" --repo "$REPO" --json attempt --jq .attempt)
|
|
|
|
# Return the latest artifact in a family, up to the given run attempt.
|
|
artifact_name() {
|
|
jq -er --arg prefix "release-github-$1-$RUN_ID-" --argjson attempt "$2" '
|
|
[.[]
|
|
| select(.name | startswith($prefix))
|
|
| . + {attempt: (.name | ltrimstr($prefix) | tonumber)}
|
|
| select(.attempt <= $attempt)]
|
|
| max_by(.attempt)
|
|
| if . == null then error("Missing artifact: \($prefix)*")
|
|
elif .expired then error("Artifact has expired: \(.name)")
|
|
else .name end
|
|
' workflow-artifacts.json
|
|
}
|
|
|
|
# Successful upstream jobs may come from earlier attempts. Anchor their selection
|
|
# to the last hosted manifest, excluding outputs from any later failed rerun.
|
|
manifest_artifact=$(artifact_name manifest "$RUN_ATTEMPT")
|
|
manifest_attempt=${manifest_artifact##*-}
|
|
gh run download "$RUN_ID" --repo "$REPO" --name "$manifest_artifact" --dir artifacts
|
|
for artifact in archives global; do
|
|
name=$(artifact_name "$artifact" "$manifest_attempt")
|
|
gh run download "$RUN_ID" --repo "$REPO" \
|
|
--name "$name" --dir artifacts
|
|
done
|
|
|
|
MANIFEST="artifacts/dist-manifest.json"
|
|
"$SCRIPT_DIR/dist-manifest-to-files.sh" "$MANIFEST" > release-assets.txt
|
|
assets=()
|
|
while IFS= read -r asset; do
|
|
assets+=("$asset")
|
|
done < release-assets.txt
|
|
|
|
# Extract values from manifest
|
|
TAG=$(jq -r '.announcement_tag // .tag' "$MANIFEST")
|
|
TITLE=$(jq -r '.announcement_title' "$MANIFEST")
|
|
BODY=$(jq -r '.announcement_github_body' "$MANIFEST")
|
|
PRERELEASE=$(jq -r '.announcement_is_prerelease' "$MANIFEST")
|
|
|
|
# Write body to temp file
|
|
echo "$BODY" > notes.txt
|
|
|
|
# Create release
|
|
release_args=(
|
|
"$TAG"
|
|
--target "$COMMIT"
|
|
--title "$TITLE"
|
|
--notes-file notes.txt
|
|
)
|
|
|
|
if [ "$PRERELEASE" = "true" ]; then
|
|
release_args+=(--prerelease)
|
|
fi
|
|
|
|
gh release create "${release_args[@]}" "${assets[@]}"
|