groupoid 0.1.0.dev4__tar.gz → 0.1.0.dev5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/.github/dependabot.yml +9 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/.github/workflows/auto-tag-release.yml +33 -14
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/.github/workflows/ci.yml +27 -20
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/.github/workflows/docs-deploy.yml +2 -2
- groupoid-0.1.0.dev5/.github/workflows/release.yml +222 -0
- groupoid-0.1.0.dev5/.zenodo.json +39 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/CHANGELOG.md +49 -2
- groupoid-0.1.0.dev5/CITATION.cff +35 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/CONTRIBUTING.md +16 -7
- groupoid-0.1.0.dev5/CORRECTION_NOTICE.md +147 -0
- groupoid-0.1.0.dev5/LIMITATIONS.md +114 -0
- {groupoid-0.1.0.dev4/groupoid.egg-info → groupoid-0.1.0.dev5}/PKG-INFO +47 -37
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/PROBLEMS.md +60 -28
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/README.md +45 -35
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/SECURITY.md +10 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/STATUS.md +21 -17
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/codemeta.json +2 -2
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/docs/api.md +16 -2
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/docs/index.md +16 -13
- groupoid-0.1.0.dev5/docs/quickstart.md +100 -0
- groupoid-0.1.0.dev5/docs/theory.md +200 -0
- groupoid-0.1.0.dev5/experiments/README.md +68 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/groupoid/__init__.py +19 -3
- groupoid-0.1.0.dev5/groupoid/aggregation.py +380 -0
- groupoid-0.1.0.dev5/groupoid/cohomology.py +170 -0
- groupoid-0.1.0.dev5/groupoid/groupoid.py +120 -0
- groupoid-0.1.0.dev5/groupoid/transport.py +187 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5/groupoid.egg-info}/PKG-INFO +47 -37
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/groupoid.egg-info/SOURCES.txt +5 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/pyproject.toml +2 -2
- groupoid-0.1.0.dev5/scripts/bind_release_sbom.py +198 -0
- groupoid-0.1.0.dev5/tests/test_cohomology_cocycle.py +169 -0
- groupoid-0.1.0.dev5/tests/test_coverage_gaps.py +186 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/tests/test_imports.py +9 -1
- groupoid-0.1.0.dev5/tests/test_integration.py +208 -0
- groupoid-0.1.0.dev5/tests/test_pipeline_integration.py +89 -0
- groupoid-0.1.0.dev5/tests/test_release_sbom_binding.py +156 -0
- groupoid-0.1.0.dev5/tests/test_release_workflow_integrity.py +100 -0
- groupoid-0.1.0.dev5/tests/test_scientific_corrections.py +552 -0
- groupoid-0.1.0.dev5/tests/theory/test_mathematical_invariants.py +120 -0
- groupoid-0.1.0.dev4/.github/workflows/release.yml +0 -107
- groupoid-0.1.0.dev4/.zenodo.json +0 -39
- groupoid-0.1.0.dev4/CITATION.cff +0 -35
- groupoid-0.1.0.dev4/LIMITATIONS.md +0 -87
- groupoid-0.1.0.dev4/docs/quickstart.md +0 -123
- groupoid-0.1.0.dev4/docs/theory.md +0 -107
- groupoid-0.1.0.dev4/experiments/README.md +0 -64
- groupoid-0.1.0.dev4/groupoid/aggregation.py +0 -299
- groupoid-0.1.0.dev4/groupoid/cohomology.py +0 -99
- groupoid-0.1.0.dev4/groupoid/groupoid.py +0 -90
- groupoid-0.1.0.dev4/groupoid/transport.py +0 -188
- groupoid-0.1.0.dev4/tests/test_cohomology_cocycle.py +0 -245
- groupoid-0.1.0.dev4/tests/test_coverage_gaps.py +0 -242
- groupoid-0.1.0.dev4/tests/test_integration.py +0 -253
- groupoid-0.1.0.dev4/tests/test_pipeline_integration.py +0 -130
- groupoid-0.1.0.dev4/tests/theory/test_mathematical_invariants.py +0 -166
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/.github/ISSUE_TEMPLATE/mathematical_correction.md +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/.github/scripts/install_torch_cpu.sh +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/.gitignore +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/.pre-commit-config.yaml +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/LICENSE +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/REPRODUCE.md +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/benchmarks/__init__.py +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/benchmarks/conftest.py +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/benchmarks/test_karcher_benchmark.py +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/docs/overrides/404.html +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/examples/README.md +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/examples/__init__.py +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/examples/synthetic_curve_demo.py +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/experiments/PREREGISTRATION.md +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/experiments/RESULTS.md +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/experiments/analyze.py +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/experiments/results.json +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/experiments/run_benchmark.py +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/groupoid/laplacian.py +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/groupoid/manifold.py +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/groupoid/optimizer.py +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/groupoid/persistence.py +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/groupoid/sheaf.py +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/groupoid.egg-info/dependency_links.txt +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/groupoid.egg-info/requires.txt +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/groupoid.egg-info/top_level.txt +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/mkdocs.yml +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/scripts/reproduce_sheaf_laplacian.py +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/setup.cfg +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/tests/__init__.py +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/tests/test_aggregation_disconnected.py +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/tests/test_defensive_paths.py +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/tests/test_optimizer_validation.py +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/tests/test_persistence.py +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/tests/test_persistence_dimension_labels.py +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/tests/test_sheaf_laplacian.py +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/tests/test_smoke.py +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/tests/test_transport_validation.py +0 -0
- {groupoid-0.1.0.dev4 → groupoid-0.1.0.dev5}/tests/theory/__init__.py +0 -0
|
@@ -28,6 +28,15 @@ updates:
|
|
|
28
28
|
# updates patch vulnerable dependencies regardless of this allow filter.
|
|
29
29
|
allow:
|
|
30
30
|
- dependency-type: "direct"
|
|
31
|
+
# numpy 2.x is a verified runtime incompatibility, not a routine bump:
|
|
32
|
+
# geomstats (a required runtime dependency) fails at import under
|
|
33
|
+
# numpy>=2.0 because `numpy.trapz` was removed, so the tested
|
|
34
|
+
# numpy>=1.24,<2.0 contract in pyproject.toml cannot widen (see closed
|
|
35
|
+
# PR #57). Scoped by version, not a blanket numpy ignore: compatible
|
|
36
|
+
# numpy 1.x version updates and 1.x security updates still flow.
|
|
37
|
+
ignore:
|
|
38
|
+
- dependency-name: "numpy"
|
|
39
|
+
versions: [">=2.0.0"]
|
|
31
40
|
groups:
|
|
32
41
|
# Batch updates by area into a single PR per group to limit noise instead
|
|
33
42
|
# of one PR per package.
|
|
@@ -1,18 +1,27 @@
|
|
|
1
1
|
name: Auto Tag Release
|
|
2
2
|
|
|
3
|
-
# Creates the tag for a release-cut merge to main
|
|
3
|
+
# Creates the tag for a release-cut merge to main, then explicitly dispatches
|
|
4
4
|
# release.yml (build, attestations, PyPI publish, signing, GitHub Release)
|
|
5
|
-
#
|
|
6
|
-
# manual `git tag vX.Y.Z && git push origin vX.Y.Z`. Keeping tag creation
|
|
7
|
-
# and publishing in two separate, single-purpose workflows means the
|
|
8
|
-
# actual publish path has exactly one trigger (a tag push) to reason
|
|
9
|
-
# about, instead of depending on GitHub's anti-recursion behavior for
|
|
10
|
-
# GITHUB_TOKEN-authored pushes not re-triggering the same push event.
|
|
5
|
+
# against that tag.
|
|
11
6
|
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
7
|
+
# The dispatch is explicit, not a tag-push trigger, because GitHub suppresses
|
|
8
|
+
# push-triggered workflow runs caused by a GITHUB_TOKEN-authored push: pushing
|
|
9
|
+
# the tag here does NOT cause release.yml's `on.push.tags` trigger to fire.
|
|
10
|
+
# workflow_dispatch is the documented exception to that suppression, which is
|
|
11
|
+
# why this workflow calls `gh workflow run` instead of relying on the tag
|
|
12
|
+
# push itself. (An earlier version of this workflow assumed the tag push
|
|
13
|
+
# alone would trigger release.yml; it did not, and no release was produced
|
|
14
|
+
# for v0.1.0.dev4 until this was fixed and the release re-run manually.)
|
|
15
|
+
#
|
|
16
|
+
# release.yml's own `push.tags` trigger remains as a fallback/manual path
|
|
17
|
+
# (a human pushing a tag with their own credentials is not subject to this
|
|
18
|
+
# suppression), alongside its `workflow_dispatch` trigger for republishing an
|
|
19
|
+
# existing tag to PyPI only.
|
|
20
|
+
#
|
|
21
|
+
# If a version needs a tag this workflow's format check rejects (see below),
|
|
22
|
+
# tag it manually -- this automation only ever creates a tag when one is
|
|
23
|
+
# missing, so a pre-existing manual tag always takes precedence and this
|
|
24
|
+
# workflow becomes a no-op for that version.
|
|
16
25
|
|
|
17
26
|
on:
|
|
18
27
|
push:
|
|
@@ -27,13 +36,16 @@ jobs:
|
|
|
27
36
|
tag:
|
|
28
37
|
runs-on: ubuntu-latest
|
|
29
38
|
permissions:
|
|
30
|
-
contents: write # push the tag
|
|
39
|
+
contents: write # push the tag
|
|
40
|
+
actions: write # dispatch release.yml via `gh workflow run`
|
|
31
41
|
steps:
|
|
32
|
-
- uses: actions/checkout@
|
|
42
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
33
43
|
with:
|
|
34
44
|
fetch-depth: 0 # need full tag history to check for an existing tag
|
|
35
45
|
|
|
36
|
-
- name: Create the release tag if this version doesn't have one yet
|
|
46
|
+
- name: Create the release tag if this version doesn't have one yet, and dispatch the release
|
|
47
|
+
env:
|
|
48
|
+
GH_TOKEN: ${{ github.token }}
|
|
37
49
|
run: |
|
|
38
50
|
set -euo pipefail
|
|
39
51
|
|
|
@@ -70,3 +82,10 @@ jobs:
|
|
|
70
82
|
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
71
83
|
git tag -a "${tag}" -m "Release ${tag}"
|
|
72
84
|
git push origin "refs/tags/${tag}"
|
|
85
|
+
|
|
86
|
+
echo "Dispatching release.yml for ${tag}."
|
|
87
|
+
gh workflow run release.yml \
|
|
88
|
+
--repo "${GITHUB_REPOSITORY}" \
|
|
89
|
+
--ref "${tag}" \
|
|
90
|
+
-f "ref=${tag}" \
|
|
91
|
+
-f "create_github_release=true"
|
|
@@ -13,8 +13,8 @@ jobs:
|
|
|
13
13
|
lint:
|
|
14
14
|
runs-on: ubuntu-latest
|
|
15
15
|
steps:
|
|
16
|
-
- uses: actions/checkout@
|
|
17
|
-
- uses: actions/setup-python@
|
|
16
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
17
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
18
18
|
with:
|
|
19
19
|
python-version: "3.11"
|
|
20
20
|
- name: Install dependencies
|
|
@@ -40,8 +40,8 @@ jobs:
|
|
|
40
40
|
matrix:
|
|
41
41
|
python-version: ["3.10", "3.11", "3.12"]
|
|
42
42
|
steps:
|
|
43
|
-
- uses: actions/checkout@
|
|
44
|
-
- uses: actions/setup-python@
|
|
43
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
44
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
45
45
|
with:
|
|
46
46
|
python-version: ${{ matrix.python-version }}
|
|
47
47
|
- name: Install dependencies
|
|
@@ -58,8 +58,8 @@ jobs:
|
|
|
58
58
|
security:
|
|
59
59
|
runs-on: ubuntu-latest
|
|
60
60
|
steps:
|
|
61
|
-
- uses: actions/checkout@
|
|
62
|
-
- uses: actions/setup-python@
|
|
61
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
62
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
63
63
|
with:
|
|
64
64
|
python-version: "3.11"
|
|
65
65
|
- name: Install dependencies
|
|
@@ -83,20 +83,27 @@ jobs:
|
|
|
83
83
|
- name: Audit dependencies for known vulnerabilities (pip-audit)
|
|
84
84
|
# pip-audit (OSV-backed, maintained) replaces the deprecated `safety check`
|
|
85
85
|
# (deprecated in safety 3.x in favour of the account-gated `safety scan`).
|
|
86
|
-
# HARD gate: any advisory with a fix version fails the job.
|
|
87
|
-
#
|
|
88
|
-
#
|
|
89
|
-
# v2.6.0) as a
|
|
90
|
-
#
|
|
91
|
-
# torch.load / JIT
|
|
92
|
-
#
|
|
93
|
-
|
|
86
|
+
# HARD gate: any advisory with a fix version fails the job. Two documented
|
|
87
|
+
# exceptions, both disclosed in SECURITY.md:
|
|
88
|
+
# - CVE-2025-3000 (torch): no fixed release exists upstream, and OSV
|
|
89
|
+
# expresses the affected range (listed versions up to v2.6.0) as a
|
|
90
|
+
# Git/commit boundary pip-audit cannot version-resolve, so it
|
|
91
|
+
# conservatively flags the installed torch. The torch.load / JIT
|
|
92
|
+
# deserialization path is not exercised by GROUPOID. Revisit the ignore
|
|
93
|
+
# once upstream publishes a fixed release.
|
|
94
|
+
# - PYSEC-2026-3447 (CVE-2026-59890, setuptools <83): the fix (83.0.0) is
|
|
95
|
+
# unreachable while torch requires setuptools<82 (see the install step
|
|
96
|
+
# above). The flaw is a macOS-only (APFS/HFS+) Unicode-normalization
|
|
97
|
+
# bypass of MANIFEST.in exclude rules when building sdists; all CI and
|
|
98
|
+
# release builds run on ubuntu-latest. Drop the ignore once torch
|
|
99
|
+
# permits setuptools>=83.
|
|
100
|
+
run: pip-audit --ignore-vuln CVE-2025-3000 --ignore-vuln PYSEC-2026-3447
|
|
94
101
|
|
|
95
102
|
pre-commit:
|
|
96
103
|
runs-on: ubuntu-latest
|
|
97
104
|
steps:
|
|
98
|
-
- uses: actions/checkout@
|
|
99
|
-
- uses: actions/setup-python@
|
|
105
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
106
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
100
107
|
with:
|
|
101
108
|
python-version: "3.11"
|
|
102
109
|
- name: Install pre-commit
|
|
@@ -107,8 +114,8 @@ jobs:
|
|
|
107
114
|
benchmark:
|
|
108
115
|
runs-on: ubuntu-latest
|
|
109
116
|
steps:
|
|
110
|
-
- uses: actions/checkout@
|
|
111
|
-
- uses: actions/setup-python@
|
|
117
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
118
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
112
119
|
with:
|
|
113
120
|
python-version: "3.11"
|
|
114
121
|
- name: Install dependencies
|
|
@@ -137,8 +144,8 @@ jobs:
|
|
|
137
144
|
docs:
|
|
138
145
|
runs-on: ubuntu-latest
|
|
139
146
|
steps:
|
|
140
|
-
- uses: actions/checkout@
|
|
141
|
-
- uses: actions/setup-python@
|
|
147
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
148
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
142
149
|
with:
|
|
143
150
|
python-version: "3.11"
|
|
144
151
|
- name: Install dependencies
|
|
@@ -16,8 +16,8 @@ jobs:
|
|
|
16
16
|
build:
|
|
17
17
|
runs-on: ubuntu-latest
|
|
18
18
|
steps:
|
|
19
|
-
- uses: actions/checkout@
|
|
20
|
-
- uses: actions/setup-python@
|
|
19
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
20
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
21
21
|
with:
|
|
22
22
|
python-version: "3.11"
|
|
23
23
|
- name: Install dependencies
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v[0-9]*"
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
inputs:
|
|
9
|
+
ref:
|
|
10
|
+
description: "Existing tag/ref to build and publish (e.g. v0.1.0.dev1). Leave blank for a normal tag-triggered release."
|
|
11
|
+
required: false
|
|
12
|
+
default: ""
|
|
13
|
+
create_github_release:
|
|
14
|
+
description: "Also sign with Sigstore and create a GitHub Release (which triggers the Zenodo deposit) for this tag. Default false: PyPI publish only, for republishing an already-released tag without creating a duplicate GitHub Release. auto-tag-release.yml sets this true when it dispatches a new version's first release."
|
|
15
|
+
required: false
|
|
16
|
+
default: false
|
|
17
|
+
type: boolean
|
|
18
|
+
|
|
19
|
+
permissions:
|
|
20
|
+
contents: read
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
# Privilege separation: this job holds the attestation credentials, so it
|
|
24
|
+
# must never install the built wheel or resolve its runtime dependency
|
|
25
|
+
# graph. SBOM generation (which does both) runs in the unprivileged `sbom`
|
|
26
|
+
# job; the SBOM attestation runs in `attest-sbom`, which installs nothing.
|
|
27
|
+
build:
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
permissions:
|
|
30
|
+
contents: read
|
|
31
|
+
id-token: write # provenance OIDC
|
|
32
|
+
attestations: write # actions/attest-build-provenance
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
35
|
+
with:
|
|
36
|
+
ref: ${{ github.event.inputs.ref || github.ref }}
|
|
37
|
+
fetch-depth: 0
|
|
38
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
39
|
+
with:
|
|
40
|
+
python-version: "3.12"
|
|
41
|
+
cache: pip
|
|
42
|
+
- name: Install build tooling
|
|
43
|
+
run: python -m pip install --upgrade pip build
|
|
44
|
+
- name: Build sdist + wheel
|
|
45
|
+
run: python -m build
|
|
46
|
+
- name: Assert exactly one release wheel
|
|
47
|
+
shell: bash
|
|
48
|
+
run: |
|
|
49
|
+
set -euo pipefail
|
|
50
|
+
shopt -s nullglob
|
|
51
|
+
wheels=(dist/*.whl)
|
|
52
|
+
if (( ${#wheels[@]} != 1 )); then
|
|
53
|
+
echo "::error::expected exactly one release wheel, found ${#wheels[@]}"
|
|
54
|
+
exit 1
|
|
55
|
+
fi
|
|
56
|
+
- name: Provenance attestation (dist)
|
|
57
|
+
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
|
|
58
|
+
with:
|
|
59
|
+
subject-path: "dist/*"
|
|
60
|
+
- name: Upload dist artifacts
|
|
61
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
62
|
+
with:
|
|
63
|
+
name: release-dist
|
|
64
|
+
path: dist/
|
|
65
|
+
|
|
66
|
+
# Unprivileged by design: installing the wheel resolves and executes
|
|
67
|
+
# third-party package installs, so this job gets no id-token, no
|
|
68
|
+
# attestations, no write access of any kind.
|
|
69
|
+
sbom:
|
|
70
|
+
needs: build
|
|
71
|
+
runs-on: ubuntu-latest
|
|
72
|
+
permissions:
|
|
73
|
+
contents: read
|
|
74
|
+
steps:
|
|
75
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
76
|
+
with:
|
|
77
|
+
ref: ${{ github.event.inputs.ref || github.ref }}
|
|
78
|
+
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
79
|
+
with:
|
|
80
|
+
python-version: "3.12"
|
|
81
|
+
cache: pip
|
|
82
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
83
|
+
with:
|
|
84
|
+
name: release-dist
|
|
85
|
+
path: dist
|
|
86
|
+
- name: Generate CycloneDX SBOM from exact release wheel
|
|
87
|
+
shell: bash
|
|
88
|
+
run: |
|
|
89
|
+
set -euo pipefail
|
|
90
|
+
shopt -s nullglob
|
|
91
|
+
wheels=(dist/*.whl)
|
|
92
|
+
if (( ${#wheels[@]} != 1 )); then
|
|
93
|
+
echo "::error::expected exactly one release wheel, found ${#wheels[@]}"
|
|
94
|
+
exit 1
|
|
95
|
+
fi
|
|
96
|
+
wheel="${wheels[0]}"
|
|
97
|
+
|
|
98
|
+
python -m pip install --upgrade pip cyclonedx-bom
|
|
99
|
+
|
|
100
|
+
# Keep build tooling out of the analyzed environment. pip's --python
|
|
101
|
+
# option installs the exact wheel and its resolved runtime graph into
|
|
102
|
+
# a venv that was created without pip.
|
|
103
|
+
python -m venv --without-pip .sbom-runtime
|
|
104
|
+
python -m pip --python .sbom-runtime install "$wheel"
|
|
105
|
+
|
|
106
|
+
cyclonedx-py environment .sbom-runtime/bin/python \
|
|
107
|
+
--pyproject pyproject.toml \
|
|
108
|
+
--mc-type library \
|
|
109
|
+
--output-reproducible \
|
|
110
|
+
--output-format JSON \
|
|
111
|
+
--output-file sbom.cdx.json
|
|
112
|
+
python scripts/bind_release_sbom.py --sbom sbom.cdx.json --wheel "$wheel"
|
|
113
|
+
- name: Independently verify SBOM root against exact wheel
|
|
114
|
+
shell: bash
|
|
115
|
+
run: |
|
|
116
|
+
set -euo pipefail
|
|
117
|
+
shopt -s nullglob
|
|
118
|
+
wheels=(dist/*.whl)
|
|
119
|
+
if (( ${#wheels[@]} != 1 )); then
|
|
120
|
+
echo "::error::expected exactly one release wheel, found ${#wheels[@]}"
|
|
121
|
+
exit 1
|
|
122
|
+
fi
|
|
123
|
+
python scripts/bind_release_sbom.py --verify-only --sbom sbom.cdx.json --wheel "${wheels[0]}"
|
|
124
|
+
- name: Upload SBOM artifact
|
|
125
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
126
|
+
with:
|
|
127
|
+
name: release-sbom
|
|
128
|
+
path: sbom.cdx.json
|
|
129
|
+
|
|
130
|
+
# The only privileged SBOM step. It consumes the already-built wheel and the
|
|
131
|
+
# already-verified SBOM; it installs no packages, resolves no dependencies,
|
|
132
|
+
# and executes no project code. The SBOM describes the installed wheel's
|
|
133
|
+
# runtime closure, so it is attested to the wheel subject only — never the
|
|
134
|
+
# sdist.
|
|
135
|
+
attest-sbom:
|
|
136
|
+
needs: [build, sbom]
|
|
137
|
+
runs-on: ubuntu-latest
|
|
138
|
+
permissions:
|
|
139
|
+
contents: read
|
|
140
|
+
id-token: write # attestation OIDC
|
|
141
|
+
attestations: write # actions/attest-sbom
|
|
142
|
+
steps:
|
|
143
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
144
|
+
with:
|
|
145
|
+
name: release-dist
|
|
146
|
+
path: dist
|
|
147
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
148
|
+
with:
|
|
149
|
+
name: release-sbom
|
|
150
|
+
path: .
|
|
151
|
+
- uses: actions/attest-sbom@c604332985a26aa8cf1bdc465b92731239ec6b9e # v4.1.0
|
|
152
|
+
with:
|
|
153
|
+
subject-path: "dist/*.whl"
|
|
154
|
+
sbom-path: "sbom.cdx.json"
|
|
155
|
+
|
|
156
|
+
publish-pypi:
|
|
157
|
+
# Publication waits for the full integrity chain: build provenance
|
|
158
|
+
# (build), SBOM generation + verification (sbom), and the wheel-bound
|
|
159
|
+
# SBOM attestation (attest-sbom).
|
|
160
|
+
needs: [build, sbom, attest-sbom]
|
|
161
|
+
runs-on: ubuntu-latest
|
|
162
|
+
permissions:
|
|
163
|
+
contents: read
|
|
164
|
+
id-token: write # PyPI Trusted Publishing OIDC
|
|
165
|
+
environment:
|
|
166
|
+
name: pypi
|
|
167
|
+
url: https://pypi.org/project/groupoid/
|
|
168
|
+
steps:
|
|
169
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
170
|
+
with:
|
|
171
|
+
name: release-dist
|
|
172
|
+
path: dist
|
|
173
|
+
- name: Publish to PyPI (Trusted Publishing, OIDC)
|
|
174
|
+
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
|
|
175
|
+
with:
|
|
176
|
+
packages-dir: dist
|
|
177
|
+
print-hash: true
|
|
178
|
+
# Idempotent: a re-dispatch or an out-of-band manual republish of a
|
|
179
|
+
# version already on PyPI should not fail the job.
|
|
180
|
+
skip-existing: true
|
|
181
|
+
|
|
182
|
+
sign-and-release:
|
|
183
|
+
needs: [build, sbom, attest-sbom]
|
|
184
|
+
# On a real tag push, or an explicit request via create_github_release=true
|
|
185
|
+
# (see auto-tag-release.yml, which dispatches this workflow with that flag
|
|
186
|
+
# set for a version's first release, since GitHub suppresses push-triggered
|
|
187
|
+
# workflow runs caused by its own GITHUB_TOKEN). A plain workflow_dispatch
|
|
188
|
+
# republish (create_github_release left at its false default) must NOT
|
|
189
|
+
# create a duplicate GitHub Release or trigger a second Zenodo deposit.
|
|
190
|
+
if: github.event_name == 'push' || github.event.inputs.create_github_release == 'true'
|
|
191
|
+
runs-on: ubuntu-latest
|
|
192
|
+
permissions:
|
|
193
|
+
contents: write # create GitHub Release
|
|
194
|
+
id-token: write # Sigstore signing OIDC
|
|
195
|
+
steps:
|
|
196
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
197
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
198
|
+
with:
|
|
199
|
+
name: release-dist
|
|
200
|
+
path: dist
|
|
201
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
202
|
+
with:
|
|
203
|
+
name: release-sbom
|
|
204
|
+
path: .
|
|
205
|
+
- name: Sign artifacts with Sigstore
|
|
206
|
+
uses: sigstore/gh-action-sigstore-python@790bc6befb9d733738f18d8f895854b453640ec9 # v3.5.0
|
|
207
|
+
with:
|
|
208
|
+
inputs: |
|
|
209
|
+
dist/*.tar.gz
|
|
210
|
+
dist/*.whl
|
|
211
|
+
- name: Create GitHub Release
|
|
212
|
+
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
|
|
213
|
+
with:
|
|
214
|
+
# Explicit rather than relying on ref inference: on a tag push
|
|
215
|
+
# github.ref_name is already the tag, but being explicit keeps this
|
|
216
|
+
# correct regardless of trigger type.
|
|
217
|
+
tag_name: ${{ github.event.inputs.ref || github.ref_name }}
|
|
218
|
+
generate_release_notes: true
|
|
219
|
+
files: |
|
|
220
|
+
dist/*
|
|
221
|
+
sbom.cdx.json
|
|
222
|
+
*.sigstore.json
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"upload_type": "software",
|
|
3
|
+
"title": "GROUPOID: Groupoid-based aggregation for federated learning on Riemannian manifolds",
|
|
4
|
+
"version": "0.1.0.dev5",
|
|
5
|
+
"description": "<p>Pre-alpha research prototype exploring groupoid-based aggregation for federated learning on Riemannian manifolds. The supported point-valued aggregation path uses explicit invertible point actions, a cycle-basis holonomy defect diagnostic, the cellular sheaf Laplacian, and Karcher mean aggregation via geomstats. Tangent-vector parallel transport is provided separately through Schild and pole ladder utilities.</p><p><strong>Scientific correction in v0.1.0.dev5:</strong> earlier releases described the cycle-basis holonomy statistic as a first-cohomology (H^1) norm. The implementation actually computes the maximum Frobenius deviation of holonomy from identity over the particular NetworkX cycle basis. Exact zero has a flatness interpretation under explicit connectedness, completeness, invertibility, reciprocal opposite-edge registration when both directions are supplied, and complete evaluation of every cycle emitted by the NetworkX cycle-basis routine (an argument specific to the NetworkX Paton implementation exercised here, not to arbitrary cycle bases), but the nonzero magnitude is basis-dependent and is not invariant under arbitrary invertible changes of frame. The stored preregistered benchmark values are unchanged; the historical H2 rho and permutation p-value are reinterpreted as statistics for this fixed cycle-basis defect, not for a canonical H^1 norm. This version also withdraws register_transport_from_points from the supported point-valued aggregation path: its ambient square operator is assembled from transported tangent vectors and does not generally define the invertible manifold point action that aggregation requires. Tangent-vector ladder validation remains supported. The ambient tangent-matrix helper is restricted to vector-shaped point representations. Direct registered matrices are supported only under the explicit point-action contract documented in the repository, including reciprocal opposite arrows when both orientations are stored. See CORRECTION_NOTICE.md for the full correction record.</p><p>The earlier v0.1.0.dev0 version DOI 10.5281/zenodo.20563975 remains superseded and must not be cited for results. Exact historical versions should be cited by their version-specific DOI; project-level DOI metadata is maintained through the Zenodo version family.</p>",
|
|
6
|
+
"creators": [
|
|
7
|
+
{
|
|
8
|
+
"name": "Maniches, Santiago",
|
|
9
|
+
"affiliation": "TOPOLOGICA LLC",
|
|
10
|
+
"orcid": "0009-0005-6480-1987"
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
"license": "Apache-2.0",
|
|
14
|
+
"keywords": [
|
|
15
|
+
"federated learning",
|
|
16
|
+
"Riemannian geometry",
|
|
17
|
+
"groupoid",
|
|
18
|
+
"sheaf theory",
|
|
19
|
+
"holonomy",
|
|
20
|
+
"topological data analysis"
|
|
21
|
+
],
|
|
22
|
+
"related_identifiers": [
|
|
23
|
+
{
|
|
24
|
+
"identifier": "10.5281/zenodo.20563974",
|
|
25
|
+
"relation": "isVersionOf",
|
|
26
|
+
"scheme": "doi"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"identifier": "10.5281/zenodo.21230068",
|
|
30
|
+
"relation": "isNewVersionOf",
|
|
31
|
+
"scheme": "doi"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"identifier": "https://github.com/smaniches/GROUPOID",
|
|
35
|
+
"relation": "isSupplementTo",
|
|
36
|
+
"scheme": "url"
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
}
|
|
@@ -8,7 +8,53 @@ this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
## [0.1.0.dev5]
|
|
12
|
+
|
|
13
|
+
Scientific correction release. See `CORRECTION_NOTICE.md` for the evidence and
|
|
14
|
+
scope. Historical preregistration and result artifacts are preserved unchanged.
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
- **The former `H^1` scalar is now identified by the quantity actually
|
|
18
|
+
computed.** `cycle_basis_holonomy_defect` returns
|
|
19
|
+
`max_{gamma in B} ||Hol(gamma) - I||_F` over the NetworkX cycle basis. The
|
|
20
|
+
historical `compute_h1` name remains as a deprecated compatibility alias.
|
|
21
|
+
The exact zero set has a flatness interpretation under explicit connected,
|
|
22
|
+
complete, invertible edge-transport assumptions with every cycle emitted by
|
|
23
|
+
`networkx.cycle_basis` evaluated -- an argument specific to the emission
|
|
24
|
+
order of the NetworkX Paton implementation exercised here, not to arbitrary
|
|
25
|
+
cycle bases -- but the nonzero magnitude is cycle-basis-dependent and is not
|
|
26
|
+
invariant under arbitrary invertible changes of frame. Finite threshold
|
|
27
|
+
decisions are therefore representation-dependent diagnostics, not canonical
|
|
28
|
+
cohomological verdicts.
|
|
29
|
+
- **Tangent-vector transport is no longer promoted into an unsupported
|
|
30
|
+
point-valued morphism.** `compute_tangent_transport_matrix` now names the
|
|
31
|
+
ambient-coordinate tangent operator explicitly. The old
|
|
32
|
+
`compute_transport_matrix` name remains as a deprecated alias.
|
|
33
|
+
`register_transport_from_points` is retained only as a compatibility stub
|
|
34
|
+
and fails closed because tangent parallel transport does not by itself define
|
|
35
|
+
the invertible point action required by the current aggregator.
|
|
36
|
+
- **Direct transport registration now states and checks the point-action
|
|
37
|
+
contract exercised by aggregation.** Registered matrices must be finite,
|
|
38
|
+
square and invertible, and actual forward and return images must remain on
|
|
39
|
+
the configured manifold. This validates exercised point actions, not
|
|
40
|
+
arbitrary matrices as generic geometric transports. The supported S^2
|
|
41
|
+
evidence continues to use explicit SO(3) rotations.
|
|
42
|
+
- **Benchmark H2 interpretation corrected without changing its historical
|
|
43
|
+
numerical result.** The committed rho=0.587 and permutation p=0.00010 are
|
|
44
|
+
retained as the association between aggregation error and the fixed
|
|
45
|
+
cycle-basis holonomy-defect statistic across pooled corruption levels; the
|
|
46
|
+
near-zero within-level correlations remain an explicit caveat.
|
|
47
|
+
- **Preregistration provenance language calibrated.** Current explanatory
|
|
48
|
+
documentation distinguishes Git commit-order evidence from the separate
|
|
49
|
+
project-record assertion that the preregistration was pushed before local
|
|
50
|
+
benchmark execution. The locked preregistration is unchanged.
|
|
51
|
+
- **Release automation now explicitly dispatches the release workflow after
|
|
52
|
+
creating a tag.** The initial 0.1.0.dev4 auto-tag path used the workflow
|
|
53
|
+
`GITHUB_TOKEN`; the resulting tag push did not trigger the tag-push release
|
|
54
|
+
workflow. The 0.1.0.dev4 GitHub Release was subsequently produced after a
|
|
55
|
+
manual workflow run. The current auto-tag workflow explicitly dispatches
|
|
56
|
+
`release.yml` so future automated release cuts do not rely on a suppressed
|
|
57
|
+
bot-authored push event.
|
|
12
58
|
|
|
13
59
|
## [0.1.0.dev4] - 2026-07-06
|
|
14
60
|
|
|
@@ -154,7 +200,8 @@ Date shown is the tag commit (`v0.1.0.dev0` -> 2a02954). `CITATION.cff` records
|
|
|
154
200
|
`date-released: 2026-05-25`, when the core implementation landed; the tag was
|
|
155
201
|
later placed on the metadata commit.
|
|
156
202
|
|
|
157
|
-
[Unreleased]: https://github.com/smaniches/GROUPOID/compare/v0.1.0.
|
|
203
|
+
[Unreleased]: https://github.com/smaniches/GROUPOID/compare/v0.1.0.dev5...HEAD
|
|
204
|
+
[0.1.0.dev5]: https://github.com/smaniches/GROUPOID/compare/v0.1.0.dev4...v0.1.0.dev5
|
|
158
205
|
[0.1.0.dev4]: https://github.com/smaniches/GROUPOID/compare/v0.1.0.dev2...v0.1.0.dev4
|
|
159
206
|
[0.1.0.dev3]: https://github.com/smaniches/GROUPOID/compare/v0.1.0.dev2...af42cb4
|
|
160
207
|
[0.1.0.dev2]: https://github.com/smaniches/GROUPOID/compare/v0.1.0.dev1...v0.1.0.dev2
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use this software, please cite the Concept DOI below so the citation resolves to the latest version."
|
|
3
|
+
type: software
|
|
4
|
+
title: "GROUPOID: Groupoid-based aggregation for federated learning on Riemannian manifolds"
|
|
5
|
+
version: 0.1.0.dev5
|
|
6
|
+
license: Apache-2.0
|
|
7
|
+
repository-code: "https://github.com/smaniches/GROUPOID"
|
|
8
|
+
doi: 10.5281/zenodo.20563974
|
|
9
|
+
identifiers:
|
|
10
|
+
- type: doi
|
|
11
|
+
value: 10.5281/zenodo.20563974
|
|
12
|
+
description: "Concept DOI (all versions)."
|
|
13
|
+
- type: doi
|
|
14
|
+
value: 10.5281/zenodo.20563975
|
|
15
|
+
description: "Version DOI (v0.1.0.dev0) - SUPERSEDED. Do not cite this historical snapshot for current results."
|
|
16
|
+
authors:
|
|
17
|
+
- family-names: Maniches
|
|
18
|
+
given-names: Santiago
|
|
19
|
+
email: santiago.maniches@gmail.com
|
|
20
|
+
affiliation: TOPOLOGICA LLC
|
|
21
|
+
orcid: "https://orcid.org/0009-0005-6480-1987"
|
|
22
|
+
keywords:
|
|
23
|
+
- federated learning
|
|
24
|
+
- Riemannian geometry
|
|
25
|
+
- groupoid
|
|
26
|
+
- sheaf theory
|
|
27
|
+
- holonomy
|
|
28
|
+
- topological data analysis
|
|
29
|
+
abstract: >-
|
|
30
|
+
Pre-alpha research prototype for groupoid-based aggregation on Riemannian
|
|
31
|
+
manifolds. The supported point-valued path uses explicit invertible point
|
|
32
|
+
actions, a basis-dependent cycle-holonomy defect diagnostic, the cellular
|
|
33
|
+
sheaf Laplacian, and Karcher mean aggregation. Tangent-vector parallel
|
|
34
|
+
transport utilities are provided separately. Earlier H^1-norm terminology
|
|
35
|
+
is superseded by the construct definition in CORRECTION_NOTICE.md.
|
|
@@ -88,8 +88,7 @@ please open an issue using the "Mathematical Correction" template.
|
|
|
88
88
|
2. Merge the PR to `main`.
|
|
89
89
|
|
|
90
90
|
That's it — merging is the release trigger, split across two workflows
|
|
91
|
-
with one job each
|
|
92
|
-
reason about:
|
|
91
|
+
with one job each:
|
|
93
92
|
|
|
94
93
|
- `.github/workflows/auto-tag-release.yml` runs on every push to `main`
|
|
95
94
|
that touches `pyproject.toml`. It reads the version out of
|
|
@@ -97,13 +96,23 @@ reason about:
|
|
|
97
96
|
pushes one (as `github-actions[bot]`) after checking the version has a
|
|
98
97
|
recognized format and that `CHANGELOG.md` documents it. A push with no
|
|
99
98
|
version change, or whose tag already exists, is a no-op.
|
|
100
|
-
-
|
|
101
|
-
|
|
99
|
+
- It then explicitly dispatches `.github/workflows/release.yml` against
|
|
100
|
+
that tag with `create_github_release: true`, rather than relying on the
|
|
101
|
+
tag push itself to trigger it. This is necessary, not a stylistic
|
|
102
|
+
choice: GitHub suppresses push-triggered workflow runs caused by a
|
|
103
|
+
`GITHUB_TOKEN`-authored push, so the tag push from
|
|
104
|
+
`auto-tag-release.yml` does *not* fire `release.yml`'s own
|
|
105
|
+
`push.tags` trigger (`workflow_dispatch` is the documented exception to
|
|
106
|
+
that suppression). `release.yml` then does what it always did: build,
|
|
102
107
|
provenance and SBOM attestation, publish to PyPI via Trusted
|
|
103
108
|
Publishing, Sigstore signing, and a GitHub Release (which in turn
|
|
104
|
-
triggers the Zenodo deposit for the new version DOI).
|
|
105
|
-
|
|
106
|
-
|
|
109
|
+
triggers the Zenodo deposit for the new version DOI).
|
|
110
|
+
- `release.yml`'s `push.tags` trigger remains as a fallback/manual path —
|
|
111
|
+
a human pushing a tag with their own credentials is not subject to the
|
|
112
|
+
`GITHUB_TOKEN` suppression above, so that still works normally. Its
|
|
113
|
+
`workflow_dispatch` trigger (`create_github_release` left at its default
|
|
114
|
+
`false`) republishes an existing tag to PyPI only, without creating a
|
|
115
|
+
duplicate GitHub Release or Zenodo deposit.
|
|
107
116
|
|
|
108
117
|
The actual PyPI publish step still runs under the `pypi` GitHub
|
|
109
118
|
Environment; if that environment has required reviewers configured, the
|