1- # This workflow will test, build, and publish a Python Package using Twine
2- name : Build, Test & Publish Python Package
1+ # Build and publish Python package - runs only on release branch and GitHub releases
2+ name : Publish Python Package
33
44on :
55 push :
66 branches :
77 - release
8- - main
98 release :
109 types : [published]
11- pull_request :
12- branches : [ main, release ]
13- workflow_dispatch : # Allow manual triggering
14-
15- permissions :
16- contents : write
17- id-token : write
10+ workflow_dispatch :
1811
1912jobs :
2013 test :
2114 runs-on : ubuntu-latest
15+ permissions :
16+ contents : read
2217 strategy :
2318 matrix :
24- python-version : ["3.8 ", "3.9 ", "3.10 ", "3.11 ", "3.12 "]
25-
19+ python-version : ["3.10 ", "3.11 ", "3.12 ", "3.13 ", "3.14 "]
20+
2621 steps :
27- - uses : actions/checkout@v4
28-
22+ - uses : actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
23+
2924 - name : Set up Python ${{ matrix.python-version }}
30- uses : actions/setup-python@v5
25+ uses : actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
3126 with :
3227 python-version : ${{ matrix.python-version }}
33-
28+
3429 - name : Install dependencies
3530 run : |
3631 python -m pip install --upgrade pip
37- pip install pytest pytest-cov
32+ pip install pytest==8.3.4 pytest-cov==6.0.0
3833 pip install -e .
39-
34+
4035 - name : Verify package installation
4136 run : |
4237 python -c "import airports.airport_data; print('Package imported successfully')"
4338 python -c "from airports import airport_data; print(f'Loaded {len(airport_data.airports)} airports')"
44-
39+
4540 - name : Run tests
4641 run : |
4742 python -m pytest tests/ -v --cov=airports --cov-report=xml
48-
49- - name : Upload coverage to Codecov
50- uses : codecov/codecov-action@v4
51- with :
52- file : ./coverage.xml
53- flags : unittests
54- name : codecov-umbrella
5543
5644 build :
5745 needs : test
5846 runs-on : ubuntu-latest
59-
47+ permissions :
48+ contents : read
49+
6050 steps :
61- - uses : actions/checkout@v4
62-
51+ - uses : actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
52+
6353 - name : Set up Python
64- uses : actions/setup-python@v5
54+ uses : actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
6555 with :
6656 python-version : ' 3.x'
67-
57+
6858 - name : Install build dependencies
6959 run : |
7060 python -m pip install --upgrade pip
71- pip install build twine
72-
61+ pip install build==1.2.2 twine==6.0.1
62+
7363 - name : Check for airports data file
7464 run : |
7565 if [ ! -f "airports/data/airports.gz" ]; then
76- echo "❌ Missing airports.gz file"
66+ echo "Missing airports.gz file"
7767 echo "This file is required for the package to work."
7868 echo "Please ensure airports/data/airports.gz exists before publishing."
7969 exit 1
8070 else
81- echo "✅ Found airports.gz file"
82- # Verify it's valid
71+ echo "Found airports.gz file"
8372 python scripts/generate_airports_gz.py --verify-only
8473 fi
85-
74+
8675 - name : Build package
8776 run : python -m build
88-
77+
8978 - name : Check package
9079 run : twine check dist/*
91-
80+
9281 - name : List package contents
9382 run : |
94- echo "📦 Package contents:"
83+ echo "Package contents:"
9584 tar -tzf dist/*.tar.gz | head -20
9685 echo "..."
97- echo "✅ Package built successfully"
98-
86+ echo "Package built successfully"
87+
9988 - name : Upload build artifacts
100- uses : actions/upload-artifact@v4
89+ uses : actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
10190 with :
10291 name : python-package-distributions
10392 path : dist/
10493
10594 publish-to-testpypi :
10695 name : Publish to TestPyPI
107- # Publish to TestPyPI on main branch pushes or manual trigger
108- if : github.event_name == 'push' && github.ref == 'refs/heads/main' || github.event_name == 'workflow_dispatch'
96+ if : github.event_name == 'workflow_dispatch'
10997 needs : [test, build]
11098 runs-on : ubuntu-latest
99+ permissions :
100+ contents : read
101+ id-token : write
111102 environment :
112103 name : testpypi
113104 url : https://test.pypi.org/p/airports-py
114-
105+
115106 steps :
116107 - name : Download build artifacts
117- uses : actions/download-artifact@v4
108+ uses : actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
118109 with :
119110 name : python-package-distributions
120111 path : dist/
121-
112+
122113 - name : Publish package to TestPyPI
123- uses : pypa/gh-action-pypi-publish@release/v1
114+ uses : pypa/gh-action-pypi-publish@106e0b0b7c337fa67ed433972f777c6357f78598 # v1.13.0
124115 with :
125116 repository-url : https://test.pypi.org/legacy/
126117 print-hash : true
127118
128119 publish-to-pypi :
129120 name : Publish to PyPI
130- # Only publish to PyPI on release branch pushes
131121 if : github.event_name == 'release' || (github.event_name == 'push' && github.ref == 'refs/heads/release')
132122 needs : [test, build]
133123 runs-on : ubuntu-latest
124+ permissions :
125+ contents : read
126+ id-token : write
134127 environment :
135128 name : pypi
136129 url : https://pypi.org/p/airports-py
137-
130+
138131 steps :
139132 - name : Download build artifacts
140- uses : actions/download-artifact@v4
133+ uses : actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
141134 with :
142135 name : python-package-distributions
143136 path : dist/
144-
137+
145138 - name : Publish package to PyPI
146- uses : pypa/gh-action-pypi-publish@release/v1
139+ uses : pypa/gh-action-pypi-publish@106e0b0b7c337fa67ed433972f777c6357f78598 # v1.13.0
0 commit comments