1414 - hotfix/*
1515 - main
1616
17- env :
18- # See: https://github.com/upx/upx/releases
19- UPX_VERSION : " 4.2.4"
20-
2117jobs :
2218 init :
2319 name : Init
24- runs-on : ubuntu-22.04
25- permissions :
26- contents : read
20+ runs-on : ubuntu-24.04
2721 outputs :
2822 VERSION : ${{ steps.version.outputs.version }}
2923 VERSION_FULL : ${{ steps.version.outputs.version_full }}
@@ -46,16 +40,21 @@ jobs:
4640 name : Test
4741 permissions :
4842 id-token : write
49- contents : read
50- runs-on : ubuntu-22.04
43+ runs-on : ubuntu-24.04
5144 needs :
5245 - init
5346 strategy :
5447 fail-fast : false
5548 matrix :
49+ # Run all test suites
5650 step :
57- - test-static
58- - test-unit
51+ - static
52+ - unit
53+ # Run on all supported Python versions
54+ python-version :
55+ - ' 3.11'
56+ - ' 3.12'
57+ - ' 3.13'
5958 steps :
6059 - name : Checkout
6160 uses : actions/checkout@v4.1.7
6463 uses : actions/setup-python@v5.1.1
6564 with :
6665 cache : pip
67- python-version : " 3.12 "
66+ python-version : " 3.13 "
6867
6968 - name : Login to Azure
7069 uses : Azure/login@v2.2.0
@@ -88,115 +87,87 @@ jobs:
8887 - name : Set up dependencies
8988 run : make install-deps
9089
90+ # See: https://github.com/ungoogled-software/ungoogled-chromium/issues/2804#issuecomment-2081611387
91+ - name : Configure AppArmor profile
92+ run : |
93+ sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
94+
9195 - name : Configure environment variables
9296 run : echo "${{ secrets.DOTENV_UNIT_TESTS }}" > .env
9397
9498 - name : Run tests
95- run : make ${{ matrix.step }} version_full=${{ needs.init.outputs.VERSION_FULL }}
99+ run : make test- ${{ matrix.step }} version_full=${{ needs.init.outputs.VERSION_FULL }}
96100
97101 - name : Upload artifacts
98102 uses : actions/upload-artifact@v4.3.6
99103 if : always()
100104 with :
101105 compression-level : 9
102- name : test-results
106+ name : test-${{ matrix.step }}-${{ matrix.python-version }}
103107 path : test-reports/*
104108
105- build-app :
106- name : Build & archive app
107- permissions :
108- contents : write
109- packages : write
110- runs-on : ${{ matrix.os }}
109+ build-wheels :
110+ name : Build wheels
111+ runs-on : ubuntu-24.04
111112 needs :
112113 - init
113- - test
114- strategy :
115- fail-fast : false
116- matrix :
117- # TODO: Build for musl (Alpine Linux)
118- os :
119- # All versions of macOS supported by GitHub Actions
120- - macos-12
121- - macos-13
122- - macos-14
123- - macos-15
124- # All versions of Ubuntu supported by GitHub Actions
125- - ubuntu-20.04
126- - ubuntu-22.04
127- - ubuntu-24.04
128- # All versions of Windows supported by GitHub Actions
129- - windows-2019
130- - windows-2022
131114 steps :
132- - name : Configure Git (Windows)
133- if : runner.os == 'Windows'
134- run : git config --system core.longpaths true
135-
136115 - name : Checkout
137116 uses : actions/checkout@v4.1.2
138117
139118 - name : Set up Python
140119 uses : actions/setup-python@v5.1.1
141120 with :
142121 cache : pip
143- python-version : " 3.12"
144-
145- - name : Set up make (Windows)
146- if : runner.os == 'Windows'
147- run : |
148- choco install make
149- make --version
122+ python-version : " 3.13"
150123
151- - name : Set up UPX (Windows)
152- if : runner.os == 'Windows'
124+ - name : Set up build dependencies
153125 run : |
154- choco install upx --version ${{ env.UPX_VERSION }}
155- upx --version
126+ python3 -m pip install --upgrade pip build
156127
157- - name : Set up dependencies
128+ - name : Write version
158129 run : |
159- python3 -m pip install --upgrade pip wheel setuptools
160- make install-deps
130+ version=$(echo "${{ needs.init.outputs.VERSION }}" | sed 's/-/\.a/' | cut -d'.' -f1-4)
131+ echo '__version__ = "'${version}'"' > src/scrape_it_now/__init__.py
161132
162- - name : Set up dependencies (Windows)
163- if : runner.os == 'Windows'
133+ - name : Build wheels
164134 run : |
165- python3 -m pip install pywin32-ctypes pefile
166-
167- - name : Write version (Linux)
168- if : runner.os == 'Linux' || runner.os == 'macOS'
169- run : echo '__version__ = "${{ needs.init.outputs.VERSION_FULL }}"' > app/__init__.py
170-
171- - name : Write version (Windows)
172- if : runner.os == 'Windows'
173- run : echo '__version__ = "${{ needs.init.outputs.VERSION_FULL }}"' > app\__init__.py
174-
175- - name : Build to binary
176- run : make build
177-
178- - name : Rename binary (Linux)
179- if : runner.os == 'Linux' || runner.os == 'macOS'
180- run : mv dist/scrape-it-now dist/scrape-it-now-${{ needs.init.outputs.VERSION }}-${{ matrix.os }}
181-
182- - name : Rename binary (Windows)
183- if : runner.os == 'Windows'
184- run : mv dist\scrape-it-now.exe dist\scrape-it-now-${{ needs.init.outputs.VERSION }}-${{ matrix.os }}.exe
135+ make build
185136
186137 - name : Upload artifacts
187138 uses : actions/upload-artifact@v4.3.6
188139 with :
189140 compression-level : 9
190- name : binary-${{ matrix.os }}
191- path : dist/*
141+ name : wheels
142+ path : dist/*.whl
143+
144+ attest-binaries :
145+ name : Attest binaries
146+ permissions :
147+ attestations : write
148+ id-token : write
149+ runs-on : ubuntu-24.04
150+ needs :
151+ - build-wheels
152+ steps :
153+ - name : Download artifacts
154+ uses : actions/download-artifact@v4.1.8
155+ with :
156+ merge-multiple : true
157+ path : dist
158+ pattern : wheels
159+
160+ - name : Generate attestations for binaries
161+ uses : actions/attest-build-provenance@v1.4.4
162+ with :
163+ subject-path : dist/*
192164
193165 attest-dependencies :
194- name : Attest - Dependencies
166+ name : Attest dependencies
195167 permissions :
196168 contents : write
197- runs-on : ubuntu-22.04
198- needs :
199- - test
169+ id-token : write
170+ runs-on : ubuntu-24.04
200171 steps :
201172 - name : Checkout
202173 uses : actions/checkout@v4.1.7
@@ -207,52 +178,119 @@ jobs:
207178 directoryExclusionList : docs
208179
209180 attest-sbom :
210- name : Attest - SBOM
211- runs-on : ubuntu-22.04
181+ name : Attest SBOM
182+ permissions :
183+ attestations : write
184+ id-token : write
185+ runs-on : ubuntu-24.04
212186 needs :
187+ - build-wheels
213188 - init
214- - test
215189 steps :
216190 - name : Checkout
217191 uses : actions/checkout@v4.1.7
218192
219- - name : Init Syft
193+ - name : Download artifacts
194+ uses : actions/download-artifact@v4.1.8
195+ with :
196+ merge-multiple : true
197+ path : dist
198+ pattern : wheels
199+
200+ - name : Set up Syft
220201 uses : anchore/sbom-action/download-syft@v0.16.1
221202
222- - name : Run attestation
203+ - name : Run scan
223204 run : make sbom version_full=${{ needs.init.outputs.VERSION_FULL }}
224205
206+ - name : Generate attestations for SBOM
207+ uses : actions/attest-build-provenance@v1.4.4
208+ with :
209+ subject-path : sbom-reports/*
210+
225211 - name : Upload results to release
226212 uses : actions/upload-artifact@v4.3.6
227213 with :
228214 compression-level : 9
229215 name : sbom
230216 path : sbom-reports/*
231217
218+ publish-testpypi :
219+ name : Publish to TestPyPI
220+ # The env "testpypi" has a protection rule which requires to be on the "main" or "develop" branches, which are both protected
221+ environment :
222+ name : testpypi
223+ url : https://test.pypi.org/p/scrape-it-now
224+ permissions :
225+ id-token : write
226+ runs-on : ubuntu-24.04
227+ needs :
228+ - attest-binaries
229+ - attest-dependencies
230+ - attest-sbom
231+ - test
232+ if : (github.ref == 'refs/heads/main') || (github.ref == 'refs/heads/develop')
233+ steps :
234+ - name : Download artifacts
235+ uses : actions/download-artifact@v4.1.8
236+ with :
237+ merge-multiple : true
238+ path : dist
239+ pattern : wheels
240+
241+ - name : Publish to TestPyPI
242+ uses : pypa/gh-action-pypi-publish@v1.12.2
243+ with :
244+ repository-url : https://test.pypi.org/legacy/
245+
246+ publish-pypi :
247+ name : Publish to PyPI
248+ # The env "pypi" has a protection rule which requires to be on the "main" branch, which is protected
249+ environment :
250+ name : pypi
251+ url : https://pypi.org/p/scrape-it-now
252+ permissions :
253+ id-token : write
254+ runs-on : ubuntu-24.04
255+ needs :
256+ # Always publish first to TestPyPI as a safety precaution
257+ - publish-testpypi
258+ if : github.ref == 'refs/heads/main'
259+ steps :
260+ - name : Download artifacts
261+ uses : actions/download-artifact@v4.1.8
262+ with :
263+ merge-multiple : true
264+ path : dist
265+ pattern : wheels
266+
267+ - name : Publish to PyPI
268+ uses : pypa/gh-action-pypi-publish@v1.12.2
269+
232270 publish-release :
233271 name : Publish release
234272 permissions :
235273 contents : write
236- runs-on : ubuntu-22 .04
274+ runs-on : ubuntu-24 .04
237275 needs :
276+ - attest-binaries
238277 - attest-dependencies
239278 - attest-sbom
240- - build-app
241279 - init
242- # Only publish on non-scheduled default branch
243- if : ( github.event_name != 'schedule') && (github. ref == 'refs/heads/main')
280+ - test
281+ if : github.ref == 'refs/heads/main'
244282 steps :
245283 - name : Download artifacts
246284 id : download
247285 uses : actions/download-artifact@v4.1.8
248286 with :
249287 merge-multiple : true
250- path : artifacts
288+ path : dist
251289
252290 - name : Publish
253291 uses : softprops/action-gh-release@v2.0.8
254292 with :
255- files : artifacts /*
293+ files : dist /*
256294 generate_release_notes : true
257295 make_latest : true
258296 name : scrape-it-now v${{ needs.init.outputs.VERSION }}
0 commit comments