Skip to content

Commit 073ee84

Browse files
authored
Revert release sharding, bump sigstore action to v3.5.0 (aio-libs#13297)
1 parent 9bb501f commit 073ee84

2 files changed

Lines changed: 28 additions & 127 deletions

File tree

.github/workflows/ci-cd.yml

Lines changed: 28 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,7 @@ jobs:
753753
path: ./wheelhouse/*.whl
754754

755755
deploy:
756-
name: Deploy (${{ matrix.group }})
756+
name: Deploy
757757
needs:
758758
- build-tarball
759759
- build-wheels
@@ -766,54 +766,12 @@ jobs:
766766
contents: write # IMPORTANT: mandatory for making GitHub Releases
767767
id-token: write # IMPORTANT: mandatory for trusted publishing & sigstore
768768

769-
# TAG is shared by the two release-existence steps. GITHUB_TOKEN stays scoped
770-
# to the steps that need it rather than job-wide, so third-party actions in
771-
# this job never see it in their environment.
772-
env:
773-
TAG: ${{ github.ref_name }}
774-
775-
# The required-reviewer pypi environment gates this job, so a human must
776-
# approve before anything is created or published. Release creation and
777-
# publishing all live in this one gated matrix, so a release needs a single
778-
# approval: the groups are pending together and a reviewer approves them in
779-
# one review (see the strategy comment below).
780769
environment:
781770
name: pypi
782771
url: https://pypi.org/p/aiohttp
783772

784-
strategy:
785-
# The PyPI publish and the Sigstore signing each mint one short-lived OIDC
786-
# identity per job and reuse it for every file, so signing the whole dist
787-
# set in a single job can outlast the token and fail partway through
788-
# (pypa/gh-action-pypi-publish#307). Splitting the work across groups, each
789-
# its own job with a fresh identity signing only its share, keeps every
790-
# signing loop well under the token lifetime.
791-
#
792-
# The groups run in parallel and all target the pypi environment, so they
793-
# are pending for approval at the same time and a reviewer approves them in
794-
# a single review rather than one prompt per group. The first group
795-
# (job-index 0) creates the GitHub Release and the others wait for it; each
796-
# group only ever touches its own disjoint share of dists, so the
797-
# concurrent Release asset uploads never collide. fail-fast is off and
798-
# every step is idempotent, so a single failed group can be re-run on its
799-
# own.
800-
#
801-
# Each label "N of M" self-encodes its own position and total, which is the
802-
# only source of truth for the split. Keep `group` the sole matrix axis: an
803-
# include/exclude entry would renumber strategy.job-index / job-total, but
804-
# the label-derived split below stays correct as long as job-index 0 is the
805-
# first label.
806-
fail-fast: false
807-
matrix:
808-
group:
809-
- 1 of 2
810-
- 2 of 2
811-
812773
steps:
813774
- name: Checkout
814-
# Only the release-creating group needs the repo (create-release reads
815-
# CHANGES.rst and aiohttp/__init__.py); the others only touch dist/.
816-
if: ${{ strategy.job-index == 0 }}
817775
uses: actions/checkout@v7
818776
with:
819777
submodules: true
@@ -826,64 +784,32 @@ jobs:
826784
path: dist
827785
pattern: dist-*
828786
merge-multiple: true
829-
- name: Select this group's distributions
830-
# Keep only this group's share of the dists so the job signs a bounded set.
831-
# index and count come from the "N of M" label, the single source of truth
832-
# for the split; to add a group, extend the matrix list above (e.g.
833-
# "1 of 3" .. "3 of 3").
834-
#
835-
# The split is fully deterministic: the same built dists always sort the
836-
# same way (LC_ALL=C, byte order, independent of runner locale) and land in
837-
# the same group, so re-running a single failed group reprocesses exactly
838-
# its own share and never touches another group's dists.
839-
id: group
840-
shell: bash
841-
env:
842-
GROUP: ${{ matrix.group }}
787+
- name: Collected dists
843788
run: |
844-
set -euo pipefail
845-
index=$(( ${GROUP%% of *} - 1 ))
846-
count=${GROUP##* of }
847-
shopt -s nullglob
848-
mapfile -t all < <(printf '%s\n' dist/*.whl dist/*.tar.gz | LC_ALL=C sort)
849-
i=0
850-
inputs=()
851-
for f in "${all[@]}"; do
852-
if [ "$(( i % count ))" -eq "${index}" ]; then
853-
inputs+=("${f}")
854-
else
855-
rm -f -- "${f}"
856-
fi
857-
i=$(( i + 1 ))
858-
done
859-
echo "Group ${GROUP} keeps ${#inputs[@]} of ${#all[@]} dist(s):"
860-
printf ' %s\n' "${inputs[@]}"
861-
echo "sigstore-inputs=${inputs[*]}" >> "${GITHUB_OUTPUT}"
789+
tree dist
862790
- name: Check whether the GitHub Release already exists
863-
# The first group owns Release creation. Skipping Make Release when the
864-
# release already exists lets the job be re-run after a partial failure
865-
# without hitting HTTP 422. Query the API and branch on the HTTP status,
866-
# not on prose: a 404 means "create it", any other failure (auth,
867-
# rate-limit, network) re-raises so the job fails loudly.
868-
if: ${{ strategy.job-index == 0 }}
791+
# Allows re-running the deploy job after a partial failure (e.g. PyPI
792+
# upload error) without the Make Release step failing with HTTP 422
793+
# because the tag/release was created on a prior attempt. Treat
794+
# only the literal `release not found` reply as "does not exist";
795+
# other failures (auth, rate-limit, network) re-raise so the job
796+
# fails loudly instead of falling through to Make Release.
869797
id: gh-release
870798
env:
871799
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
800+
TAG: ${{ github.ref_name }}
872801
run: |
873-
set -euo pipefail
874-
if gh api "repos/${GITHUB_REPOSITORY}/releases/tags/${TAG}" \
875-
--silent 2>err; then
802+
if gh release view "${TAG}" --repo "${GITHUB_REPOSITORY}" \
803+
>/dev/null 2>err; then
876804
echo 'exists=true' >> "${GITHUB_OUTPUT}"
877-
elif grep -q 'HTTP 404' err; then
805+
elif grep -qx 'release not found' err; then
878806
echo 'exists=false' >> "${GITHUB_OUTPUT}"
879807
else
880808
cat err >&2
881809
exit 1
882810
fi
883811
- name: Make Release
884-
# The first group creates the Release and uploads its share of the
885-
# packages; the other groups add their packages and signatures below.
886-
if: ${{ strategy.job-index == 0 && steps.gh-release.outputs.exists != 'true' }}
812+
if: steps.gh-release.outputs.exists != 'true'
887813
uses: aio-libs/create-release@v1.6.6
888814
with:
889815
changes_file: CHANGES.rst
@@ -895,52 +821,28 @@ jobs:
895821
:issue:`(\d+)`
896822
fix_issue_repl: >-
897823
#\1
898-
- name: Wait for the GitHub Release
899-
# The other groups do not create the Release; they wait for the first
900-
# group to create it before they publish or upload anything, so a failure
901-
# to create the Release blocks the irreversible PyPI upload too. Only a
902-
# 404 counts as "not yet"; any other API failure re-raises immediately
903-
# instead of silently retrying for the whole timeout.
904-
if: ${{ strategy.job-index != 0 }}
905-
env:
906-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
907-
run: |
908-
set -euo pipefail
909-
for _ in $(seq 1 150); do
910-
if gh api "repos/${GITHUB_REPOSITORY}/releases/tags/${TAG}" \
911-
--silent 2>err; then
912-
exit 0
913-
fi
914-
if ! grep -q 'HTTP 404' err; then
915-
cat err >&2
916-
exit 1
917-
fi
918-
sleep 2
919-
done
920-
echo "GitHub Release ${TAG} did not appear in time" >&2
921-
exit 1
922-
- name: Publish 🐍📦 to PyPI
824+
825+
- name: >-
826+
Publish 🐍📦 to PyPI
923827
uses: pypa/gh-action-pypi-publish@release/v1
924828
with:
925-
# Allow re-running after a partial PyPI upload without failing on
926-
# dists that a prior attempt already published.
829+
# Allow re-running the deploy job after a partial PyPI upload
830+
# without failing on dists that were already published.
927831
skip-existing: true
832+
928833
- name: Sign the dists with Sigstore
929-
uses: sigstore/gh-action-sigstore-python@v3.4.0
834+
uses: sigstore/gh-action-sigstore-python@v3.5.0
930835
with:
931-
inputs: ${{ steps.group.outputs.sigstore-inputs }}
836+
inputs: >-
837+
./dist/*.tar.gz
838+
./dist/*.whl
839+
932840
- name: Upload artifact signatures to GitHub Release
933841
# Confusingly, this action also supports updating releases, not
934-
# just creating them. This is what we want here, since the first group
842+
# just creating them. This is what we want here, since we've manually
935843
# created the release above.
936-
#
937-
# The groups run this concurrently against the same release, which is safe:
938-
# each group's files are a disjoint share, so asset names never collide, and
939-
# with no body/name inputs the action preserves the existing release
940-
# metadata (it writes back what it reads) rather than clearing it, so the
941-
# concurrent metadata updates are identical no-ops. The Wait step above
942-
# guarantees the release (with its notes) already exists first.
943844
uses: softprops/action-gh-release@v3.0.2
944845
with:
945-
# dist/ holds this group's packages plus their Sigstore signatures.
846+
# dist/ contains the built packages plus the Sigstore signatures
847+
# and certificates emitted alongside them by the signing step above.
946848
files: dist/**

CHANGES/13226.contrib.rst

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)