1
+ name : release
2
+ run-name : Release ${{ inputs.working-directory }} by @${{ github.actor }}
3
+ on :
4
+ workflow_call :
5
+ inputs :
6
+ working-directory :
7
+ required : true
8
+ type : string
9
+ description : " From which folder this pipeline executes"
10
+ workflow_dispatch :
11
+ inputs :
12
+ working-directory :
13
+ description : " From which folder this pipeline executes"
14
+ default : " ."
15
+ dangerous-nonmain-release :
16
+ required : false
17
+ type : boolean
18
+ default : false
19
+ description : " Release from a non-main branch (danger!)"
20
+
21
+ env :
22
+ PYTHON_VERSION : " 3.11"
23
+ UV_FROZEN : " true"
24
+ UV_NO_SYNC : " true"
25
+
26
+ jobs :
27
+ build :
28
+ if : github.ref == 'refs/heads/main' || inputs.dangerous-nonmain-release
29
+ environment : Scheduled testing
30
+ runs-on : ubuntu-latest
31
+
32
+ outputs :
33
+ pkg-name : ${{ steps.check-version.outputs.pkg-name }}
34
+ version : ${{ steps.check-version.outputs.version }}
35
+
36
+ steps :
37
+ - uses : actions/checkout@v4
38
+
39
+ - name : Set up Python + uv
40
+ uses : " ./.github/actions/uv_setup"
41
+ with :
42
+ python-version : ${{ env.PYTHON_VERSION }}
43
+
44
+ # We want to keep this build stage *separate* from the release stage,
45
+ # so that there's no sharing of permissions between them.
46
+ # The release stage has trusted publishing and GitHub repo contents write access,
47
+ # and we want to keep the scope of that access limited just to the release job.
48
+ # Otherwise, a malicious `build` step (e.g. via a compromised dependency)
49
+ # could get access to our GitHub or PyPI credentials.
50
+ #
51
+ # Per the trusted publishing GitHub Action:
52
+ # > It is strongly advised to separate jobs for building [...]
53
+ # > from the publish job.
54
+ # https://github.com/pypa/gh-action-pypi-publish#non-goals
55
+ - name : Build project for distribution
56
+ run : uv build
57
+ - name : Upload build
58
+ uses : actions/upload-artifact@v4
59
+ with :
60
+ name : dist
61
+ path : ${{ inputs.working-directory }}/dist/
62
+
63
+ - name : Check Version
64
+ id : check-version
65
+ shell : python
66
+ working-directory : ${{ inputs.working-directory }}
67
+ run : |
68
+ import os
69
+ import tomllib
70
+ with open("pyproject.toml", "rb") as f:
71
+ data = tomllib.load(f)
72
+ pkg_name = data["project"]["name"]
73
+ version = data["project"]["version"]
74
+ with open(os.environ["GITHUB_OUTPUT"], "a") as f:
75
+ f.write(f"pkg-name={pkg_name}\n")
76
+ f.write(f"version={version}\n")
77
+ publish :
78
+ needs :
79
+ - build
80
+ runs-on : ubuntu-latest
81
+ permissions :
82
+ # This permission is used for trusted publishing:
83
+ # https://blog.pypi.org/posts/2023-04-20-introducing-trusted-publishers/
84
+ #
85
+ # Trusted publishing has to also be configured on PyPI for each package:
86
+ # https://docs.pypi.org/trusted-publishers/adding-a-publisher/
87
+ id-token : write
88
+
89
+ defaults :
90
+ run :
91
+ working-directory : ${{ inputs.working-directory }}
92
+
93
+ steps :
94
+ - uses : actions/checkout@v4
95
+
96
+ - name : Set up Python + uv
97
+ uses : " ./.github/actions/uv_setup"
98
+ with :
99
+ python-version : ${{ env.PYTHON_VERSION }}
100
+
101
+ - uses : actions/download-artifact@v4
102
+ with :
103
+ name : dist
104
+ path : ${{ inputs.working-directory }}/dist/
105
+
106
+ - name : Publish package distributions to PyPI
107
+ uses : pypa/gh-action-pypi-publish@release/v1
108
+ with :
109
+ packages-dir : ${{ inputs.working-directory }}/dist/
110
+ verbose : true
111
+ print-hash : true
112
+ # Temp workaround since attestations are on by default as of gh-action-pypi-publish v1.11.0
113
+ attestations : false
114
+
115
+ mark-release :
116
+ needs :
117
+ - build
118
+ - publish
119
+ runs-on : ubuntu-latest
120
+ permissions :
121
+ # This permission is needed by `ncipollo/release-action` to
122
+ # create the GitHub release.
123
+ contents : write
124
+
125
+ defaults :
126
+ run :
127
+ working-directory : ${{ inputs.working-directory }}
128
+
129
+ steps :
130
+ - uses : actions/checkout@v4
131
+
132
+ - name : Set up Python + uv
133
+ uses : " ./.github/actions/uv_setup"
134
+ with :
135
+ python-version : ${{ env.PYTHON_VERSION }}
136
+
137
+ - uses : actions/download-artifact@v4
138
+ with :
139
+ name : dist
140
+ path : ${{ inputs.working-directory }}/dist/
141
+
142
+ - name : Create Tag
143
+ uses : ncipollo/release-action@v1
144
+ with :
145
+ artifacts : " dist/*"
146
+ token : ${{ secrets.GITHUB_TOKEN }}
147
+ generateReleaseNotes : true
148
+ tag : ${{needs.build.outputs.pkg-name}}==${{ needs.build.outputs.version }}
149
+ body : ${{ needs.release-notes.outputs.release-body }}
150
+ commit : main
151
+ makeLatest : true
0 commit comments