Skip to content

Commit c306931

Browse files
authored
ci: migrate PyPI publishing to OIDC authentication (#3054)
cv1.0.0i: migrate PyPI publishing to OIDC authentication Replace token-based authentication with OpenID Connect (OIDC) for enhanced security when publishing to PyPI and Test PyPI. Signed-off-by: mramotowski <maciej.ramotowski@intel.com>
1 parent 045d116 commit c306931

File tree

4 files changed

+50
-45
lines changed

4 files changed

+50
-45
lines changed

.github/workflows/_reusable-production-release-process.yaml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,12 @@
3030
# - version: Release version
3131
# - artifact-name: Name of validated artifact
3232
#
33-
# Required Secrets:
34-
# - pypi-token: Production PyPI token
33+
# Note: PyPI publishing uses OIDC (OpenID Connect) authentication.
34+
# Configure trusted publisher in PyPI project settings:
35+
# - Owner: <your-org>
36+
# - Repository name: anomalib
37+
# - Workflow name: release.yaml
38+
# - Environment name: production
3539
#
3640
# Example Usage:
3741
# 1. Production Release:
@@ -57,12 +61,10 @@ on:
5761
artifact-name:
5862
required: true
5963
type: string
60-
secrets:
61-
pypi-token:
62-
required: true
6364

6465
permissions:
6566
contents: read
67+
id-token: write # Required for OIDC authentication with PyPI
6668

6769
jobs:
6870
validate-release-readiness:
@@ -107,9 +109,8 @@ jobs:
107109
uses: ./.github/workflows/_reusable-release-publisher.yaml
108110
permissions:
109111
contents: write # is required by action-gh-release (nested)
112+
id-token: write # Required for OIDC authentication with PyPI
110113
with:
111114
version: ${{ inputs.version }}
112115
artifact-name: production-release-artifacts
113116
is-prerelease: false
114-
secrets:
115-
pypi-token: ${{ secrets.pypi-token }}

.github/workflows/_reusable-rc-release-process.yaml

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,12 @@
3535
# - version: Version to release
3636
# - artifact-name: Name of build artifact
3737
#
38-
# Required Secrets:
39-
# - test-pypi-token: PyPI token for test deployments
38+
# Note: PyPI publishing uses OIDC (OpenID Connect) authentication.
39+
# Configure trusted publisher in Test PyPI project settings:
40+
# - Owner: <your-org>
41+
# - Repository name: anomalib
42+
# - Workflow name: release.yaml
43+
# - Environment name: technical-review
4044
#
4145
# Example Usage:
4246
# 1. Standard RC Process:
@@ -62,12 +66,10 @@ on:
6266
artifact-name:
6367
required: true
6468
type: string
65-
secrets:
66-
test-pypi-token:
67-
required: true
6869

6970
permissions:
7071
contents: read
72+
id-token: write # Required for OIDC authentication with PyPI
7173

7274
jobs:
7375
technical-review:
@@ -111,13 +113,10 @@ jobs:
111113
path: quality-results
112114

113115
- name: Deploy to Test PyPI
114-
env:
115-
TWINE_USERNAME: __token__
116-
TWINE_PASSWORD: ${{ secrets.test-pypi-token }}
117-
TWINE_REPOSITORY_URL: https://test.pypi.org/legacy/
118-
run: |
119-
pip install --upgrade pip twine
120-
twine upload dist/*
116+
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
117+
with:
118+
repository-url: https://test.pypi.org/legacy/
119+
verbose: true
121120

122121
- name: Validate deployment
123122
id: validate-deployment

.github/workflows/_reusable-release-publisher.yaml

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,16 @@
3131
# - artifact-name: Name of artifact to publish
3232
# - is-prerelease: Whether this is a pre-release
3333
#
34-
# Required Secrets:
35-
# - pypi-token: Production PyPI token
36-
# - test-pypi-token: Test PyPI token (for pre-releases)
34+
# Note: PyPI publishing uses OIDC (OpenID Connect) authentication.
35+
# Configure trusted publisher in PyPI project settings:
36+
# - Owner: <your-org>
37+
# - Repository name: anomalib
38+
# - Workflow name: release.yaml
39+
# - Environment name: production
40+
#
41+
# Note: This workflow is used for production and beta releases only.
42+
# RC releases are published directly from _reusable-rc-release-process.yaml
43+
# using the 'technical-review' environment.
3744
#
3845
# Example Usage:
3946
# 1. Production Release:
@@ -66,35 +73,24 @@ on:
6673
description: "Whether this is a pre-release"
6774
type: boolean
6875
default: false
69-
secrets:
70-
pypi-token:
71-
required: true
72-
description: "PyPI token for package publishing"
73-
test-pypi-token:
74-
required: false
75-
description: "Test PyPI token for pre-releases"
7676

77-
permissions: {} # default permissions only on workflow level
77+
permissions:
78+
id-token: write # Required for OIDC authentication with PyPI
7879

7980
jobs:
8081
publish:
8182
runs-on: ubuntu-latest
8283
environment: ${{ inputs.is-prerelease && 'staging' || 'production' }}
8384
permissions:
8485
contents: write # is required by action-gh-release
86+
id-token: write # Required for OIDC authentication with PyPI
8587
steps:
8688
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
8789
with:
8890
name: ${{ inputs.artifact-name }}
8991
path: dist
9092
- name: Publish to PyPI
91-
env:
92-
TWINE_USERNAME: __token__
93-
TWINE_PASSWORD: ${{ inputs.is-prerelease && secrets.test-pypi-token || secrets.pypi-token }}
94-
TWINE_REPOSITORY_URL: ${{ inputs.is-prerelease && 'https://test.pypi.org/legacy/' || '' }}
95-
run: |
96-
pip install --upgrade pip twine
97-
twine upload dist/*
93+
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
9894
- uses: softprops/action-gh-release@62c96d0c4e8a889135c1f3a25910db8dbe0e85f7 # v2.3.4
9995
with:
10096
tag_name: ${{ inputs.version }}

.github/workflows/release.yaml

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,19 @@
2929
#
3030
# Required Secrets:
3131
# - CODECOV_TOKEN: Coverage reporting
32-
# - TEST_PYPI_TOKEN: RC deployments
33-
# - PYPI_TOKEN: Production deployments
32+
#
33+
# Note: PyPI publishing uses OIDC (OpenID Connect) authentication.
34+
# Configure trusted publishers in PyPI project settings:
35+
# - For production/beta releases (PyPI):
36+
# - Owner: <your-org>
37+
# - Repository name: anomalib
38+
# - Workflow name: release.yaml
39+
# - Environment name: production
40+
# - For RC releases (Test PyPI):
41+
# - Owner: <your-org>
42+
# - Repository name: anomalib
43+
# - Workflow name: release.yaml
44+
# - Environment name: technical-review
3445
#
3546
# Example Usage:
3647
# 1. Automated (Tag Push):
@@ -85,35 +96,33 @@ jobs:
8596
needs: [validation]
8697
if: contains(needs.validation.outputs.version, '-rc')
8798
uses: ./.github/workflows/_reusable-rc-release-process.yaml
99+
permissions:
100+
id-token: write # Required for OIDC authentication with PyPI
88101
with:
89102
version: ${{ needs.validation.outputs.version }}
90103
artifact-name: ${{ needs.validation.outputs.artifact-name }}
91-
secrets:
92-
test-pypi-token: ${{ secrets.TEST_PYPI_TOKEN }}
93104

94105
production-release-process:
95106
needs: [validation]
96107
if: ${{ !contains(needs.validation.outputs.version, '-rc') && !contains(needs.validation.outputs.version, 'b') }}
97108
uses: ./.github/workflows/_reusable-production-release-process.yaml
98109
permissions:
99110
contents: write # is required by action-gh-release (nested)
111+
id-token: write # Required for OIDC authentication with PyPI
100112
with:
101113
version: ${{ needs.validation.outputs.version }}
102114
artifact-name: ${{ needs.validation.outputs.artifact-name }}
103-
secrets:
104-
pypi-token: ${{ secrets.PYPI_TOKEN }}
105115

106116
beta-release-process:
107117
needs: [validation]
108118
if: contains(needs.validation.outputs.version, 'b')
109119
uses: ./.github/workflows/_reusable-production-release-process.yaml
110120
permissions:
111121
contents: write # is required by action-gh-release (nested)
122+
id-token: write # Required for OIDC authentication with PyPI
112123
with:
113124
version: ${{ needs.validation.outputs.version }}
114125
artifact-name: ${{ needs.validation.outputs.artifact-name }}
115-
secrets:
116-
pypi-token: ${{ secrets.PYPI_TOKEN }}
117126

118127
status:
119128
needs:

0 commit comments

Comments
 (0)