Skip to content

Commit 6a09bbb

Browse files
introduce new deploy step
1 parent 21a94db commit 6a09bbb

File tree

2 files changed

+400
-40
lines changed

2 files changed

+400
-40
lines changed
Lines changed: 316 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,316 @@
1+
name: "public/tidy3d/python-client-deploy"
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
release_tag:
7+
description: 'Release tag to deploy (e.g., v2.10.0, v2.10.0rc1)'
8+
required: true
9+
type: string
10+
11+
deploy_testpypi:
12+
description: 'Deploy to TestPyPI (recommended first step)'
13+
type: boolean
14+
default: true
15+
16+
deploy_pypi:
17+
description: 'Deploy to production PyPI'
18+
type: boolean
19+
default: false
20+
21+
deploy_aws:
22+
description: 'Deploy to AWS CodeArtifact'
23+
type: boolean
24+
default: false
25+
26+
workflow_call:
27+
inputs:
28+
release_tag:
29+
description: 'Release tag to deploy'
30+
required: true
31+
type: string
32+
deploy_testpypi:
33+
type: boolean
34+
default: false
35+
deploy_pypi:
36+
type: boolean
37+
default: false
38+
deploy_aws:
39+
type: boolean
40+
default: false
41+
42+
permissions:
43+
contents: read
44+
id-token: write
45+
46+
env:
47+
AWS_REGION: "us-east-1"
48+
49+
jobs:
50+
validate-inputs:
51+
name: validate-deployment-inputs
52+
runs-on: ubuntu-latest
53+
outputs:
54+
release_tag: ${{ env.RELEASE_TAG }}
55+
deploy_testpypi: ${{ env.DEPLOY_TESTPYPI }}
56+
deploy_pypi: ${{ env.DEPLOY_PYPI }}
57+
deploy_aws: ${{ env.DEPLOY_AWS }}
58+
env:
59+
RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.release_tag || inputs.release_tag }}
60+
DEPLOY_TESTPYPI: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.deploy_testpypi || inputs.deploy_testpypi }}
61+
DEPLOY_PYPI: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.deploy_pypi || inputs.deploy_pypi }}
62+
DEPLOY_AWS: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.deploy_aws || inputs.deploy_aws }}
63+
steps:
64+
- name: validate-inputs
65+
run: |
66+
set -e
67+
echo "=== Deployment Configuration ==="
68+
echo "Release tag: $RELEASE_TAG"
69+
echo "Deploy to TestPyPI: $DEPLOY_TESTPYPI"
70+
echo "Deploy to PyPI: $DEPLOY_PYPI"
71+
echo "Deploy to AWS CodeArtifact: $DEPLOY_AWS"
72+
echo ""
73+
74+
# Validate at least one target is selected
75+
if [[ "$DEPLOY_TESTPYPI" != "true" && "$DEPLOY_PYPI" != "true" && "$DEPLOY_AWS" != "true" ]]; then
76+
echo "? Error: At least one deployment target must be selected"
77+
exit 1
78+
fi
79+
80+
# Validate tag format
81+
TAG_REGEX='^v[0-9]+\.[0-9]+\.[0-9]+(rc[0-9]+)?$'
82+
if [[ ! "$RELEASE_TAG" =~ $TAG_REGEX ]]; then
83+
echo "?? Warning: Tag format doesn't match standard pattern v{major}.{minor}.{patch}[rc{num}]"
84+
echo " Tag: $RELEASE_TAG"
85+
echo " Continuing anyway..."
86+
fi
87+
88+
echo "? Validation passed"
89+
90+
build-package:
91+
name: build-distribution-package
92+
needs: validate-inputs
93+
runs-on: ubuntu-latest
94+
steps:
95+
- name: checkout-tag
96+
uses: actions/checkout@v4
97+
with:
98+
ref: ${{ needs.validate-inputs.outputs.release_tag }}
99+
persist-credentials: false
100+
101+
- name: setup-python
102+
uses: actions/setup-python@v5
103+
with:
104+
python-version: '3.10'
105+
106+
- name: install-poetry
107+
run: |
108+
python -m pip install --upgrade pip
109+
python -m pip install poetry
110+
111+
- name: build-package
112+
run: |
113+
echo "Building package from tag ${{ needs.validate-inputs.outputs.release_tag }}..."
114+
poetry build
115+
echo ""
116+
echo "Build artifacts:"
117+
ls -lh dist/
118+
echo ""
119+
echo "? Package built successfully"
120+
121+
- name: upload-artifacts
122+
uses: actions/upload-artifact@v4
123+
with:
124+
name: dist-${{ needs.validate-inputs.outputs.release_tag }}
125+
path: dist/
126+
retention-days: 7
127+
128+
deploy-testpypi:
129+
name: deploy-to-testpypi
130+
needs: [validate-inputs, build-package]
131+
if: needs.validate-inputs.outputs.deploy_testpypi == 'true'
132+
runs-on: ubuntu-latest
133+
steps:
134+
- name: download-artifacts
135+
uses: actions/download-artifact@v4
136+
with:
137+
name: dist-${{ needs.validate-inputs.outputs.release_tag }}
138+
path: dist/
139+
140+
- name: setup-python
141+
uses: actions/setup-python@v5
142+
with:
143+
python-version: '3.10'
144+
145+
- name: install-twine
146+
run: |
147+
python -m pip install --upgrade pip
148+
python -m pip install twine
149+
150+
- name: publish-to-testpypi
151+
env:
152+
TWINE_USERNAME: __token__
153+
TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }}
154+
run: |
155+
echo "?? Publishing to TestPyPI..."
156+
python -m twine upload \
157+
--repository-url https://test.pypi.org/legacy/ \
158+
--verbose \
159+
dist/*
160+
echo ""
161+
echo "? Successfully published to TestPyPI"
162+
echo " View at: https://test.pypi.org/project/tidy3d/"
163+
164+
deploy-pypi:
165+
name: deploy-to-pypi
166+
needs: [validate-inputs, build-package, deploy-testpypi]
167+
# Run after TestPyPI succeeds (or is skipped if not selected)
168+
if: |
169+
always() &&
170+
needs.validate-inputs.outputs.deploy_pypi == 'true' &&
171+
needs.build-package.result == 'success' &&
172+
(needs.deploy-testpypi.result == 'success' || needs.deploy-testpypi.result == 'skipped')
173+
runs-on: ubuntu-latest
174+
steps:
175+
- name: download-artifacts
176+
uses: actions/download-artifact@v4
177+
with:
178+
name: dist-${{ needs.validate-inputs.outputs.release_tag }}
179+
path: dist/
180+
181+
- name: setup-python
182+
uses: actions/setup-python@v5
183+
with:
184+
python-version: '3.10'
185+
186+
- name: install-twine
187+
run: |
188+
python -m pip install --upgrade pip
189+
python -m pip install twine
190+
191+
- name: publish-to-pypi
192+
env:
193+
TWINE_USERNAME: __token__
194+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
195+
run: |
196+
echo "?? Publishing to production PyPI..."
197+
python -m twine upload \
198+
--repository pypi \
199+
--verbose \
200+
dist/*
201+
echo ""
202+
echo "? Successfully published to PyPI"
203+
echo " View at: https://pypi.org/project/tidy3d/"
204+
205+
deploy-aws-codeartifact:
206+
name: deploy-to-aws-codeartifact
207+
needs: [validate-inputs, build-package, deploy-testpypi]
208+
# Run in parallel with PyPI after TestPyPI succeeds
209+
if: |
210+
always() &&
211+
needs.validate-inputs.outputs.deploy_aws == 'true' &&
212+
needs.build-package.result == 'success' &&
213+
(needs.deploy-testpypi.result == 'success' || needs.deploy-testpypi.result == 'skipped')
214+
runs-on: ubuntu-latest
215+
steps:
216+
- name: download-artifacts
217+
uses: actions/download-artifact@v4
218+
with:
219+
name: dist-${{ needs.validate-inputs.outputs.release_tag }}
220+
path: dist/
221+
222+
- name: setup-python
223+
uses: actions/setup-python@v5
224+
with:
225+
python-version: '3.10'
226+
227+
- name: install-twine
228+
run: |
229+
python -m pip install --upgrade pip
230+
python -m pip install twine
231+
232+
- name: configure-aws-credentials
233+
uses: aws-actions/configure-aws-credentials@v4
234+
with:
235+
aws-region: ${{ env.AWS_REGION }}
236+
aws-access-key-id: ${{ secrets.AWS_CODEARTIFACT_ACCESS_KEY }}
237+
aws-secret-access-key: ${{ secrets.AWS_CODEARTIFACT_ACCESS_SECRET }}
238+
239+
- name: configure-codeartifact-package
240+
run: |
241+
echo "?? Configuring CodeArtifact package settings..."
242+
aws codeartifact put-package-origin-configuration \
243+
--domain flexcompute \
244+
--repository pypi-releases \
245+
--format pypi \
246+
--package tidy3d \
247+
--restrictions '{"publish":"ALLOW", "upstream":"BLOCK"}'
248+
249+
- name: get-codeartifact-token
250+
run: |
251+
echo "?? Getting CodeArtifact authorization token..."
252+
CODEARTIFACT_AUTH_TOKEN=$(aws codeartifact get-authorization-token \
253+
--domain flexcompute \
254+
--domain-owner 625554095313 \
255+
--region us-east-1 \
256+
--query authorizationToken \
257+
--output text)
258+
echo "CODEARTIFACT_AUTH_TOKEN=${CODEARTIFACT_AUTH_TOKEN}" >> $GITHUB_ENV
259+
260+
- name: publish-to-codeartifact
261+
env:
262+
TWINE_PASSWORD: ${{ env.CODEARTIFACT_AUTH_TOKEN }}
263+
run: |
264+
echo "?? Publishing to AWS CodeArtifact..."
265+
python -m twine upload \
266+
--repository-url https://flexcompute-625554095313.d.codeartifact.us-east-1.amazonaws.com/pypi/pypi-releases/ \
267+
--verbose \
268+
-u aws \
269+
-p "$TWINE_PASSWORD" \
270+
dist/*
271+
echo ""
272+
echo "? Successfully published to AWS CodeArtifact"
273+
274+
deployment-summary:
275+
name: deployment-summary
276+
needs: [validate-inputs, build-package, deploy-testpypi, deploy-pypi, deploy-aws-codeartifact]
277+
if: always()
278+
runs-on: ubuntu-latest
279+
steps:
280+
- name: generate-summary
281+
run: |
282+
echo "=== Deployment Summary ==="
283+
echo "Release Tag: ${{ needs.validate-inputs.outputs.release_tag }}"
284+
echo ""
285+
echo "Build Package: ${{ needs.build-package.result }}"
286+
echo "TestPyPI: ${{ needs.deploy-testpypi.result }}"
287+
echo "PyPI: ${{ needs.deploy-pypi.result }}"
288+
echo "AWS CodeArtifact: ${{ needs.deploy-aws-codeartifact.result }}"
289+
echo ""
290+
291+
# Check for failures
292+
if [[ "${{ needs.build-package.result }}" == "failure" ]]; then
293+
echo "? Build failed"
294+
exit 1
295+
fi
296+
297+
# Check if any selected deployment failed
298+
failed=false
299+
if [[ "${{ needs.validate-inputs.outputs.deploy_testpypi }}" == "true" && "${{ needs.deploy-testpypi.result }}" == "failure" ]]; then
300+
echo "? TestPyPI deployment failed"
301+
failed=true
302+
fi
303+
if [[ "${{ needs.validate-inputs.outputs.deploy_pypi }}" == "true" && "${{ needs.deploy-pypi.result }}" == "failure" ]]; then
304+
echo "? PyPI deployment failed"
305+
failed=true
306+
fi
307+
if [[ "${{ needs.validate-inputs.outputs.deploy_aws }}" == "true" && "${{ needs.deploy-aws-codeartifact.result }}" == "failure" ]]; then
308+
echo "? AWS CodeArtifact deployment failed"
309+
failed=true
310+
fi
311+
312+
if [[ "$failed" == "true" ]]; then
313+
exit 1
314+
fi
315+
316+
echo "? All selected deployments completed successfully"

0 commit comments

Comments
 (0)