Skip to content

Commit c5976cc

Browse files
committed
Revisit GitHub Actions
1 parent 68d0a83 commit c5976cc

4 files changed

Lines changed: 229 additions & 82 deletions

File tree

Lines changed: 57 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,68 @@
1-
# This workflows will upload a Python Package using Twine when a release is created
2-
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
1+
# Publishes the package to PyPI when a GitHub Release is *published*
2+
# (not on draft creation — only when you click "Publish release").
3+
#
4+
# Authentication: uses PyPI Trusted Publisher (OIDC) — no long-lived secrets
5+
# needed. Configure a Trusted Publisher for this repo on pypi.org first:
6+
# https://docs.pypi.org/trusted-publishers/adding-a-publisher/
7+
#
8+
# If you prefer an API token instead, remove the `environment` + `permissions`
9+
# blocks and uncomment:
10+
# password: ${{ secrets.PYPI_API_TOKEN }}
11+
# in the "Publish" step below.
312

413
name: Python Client - Publish to PyPI
514

615
on:
716
release:
8-
types: [created]
17+
types: [published]
918

1019
jobs:
11-
deploy:
20+
test:
21+
name: "Test before publish"
22+
runs-on: ubuntu-latest
23+
24+
steps:
25+
- uses: actions/checkout@v4
26+
27+
- uses: actions/setup-python@v5
28+
with:
29+
python-version: "3.13"
30+
cache: pip
31+
32+
- name: Install dependencies
33+
run: pip install -e ".[dev]"
34+
35+
- name: Test with pytest
36+
run: pytest
1237

38+
publish:
39+
name: "Build and publish to PyPI"
1340
runs-on: ubuntu-latest
41+
needs: test
42+
43+
environment: pypi
44+
permissions:
45+
id-token: write # required for OIDC Trusted Publisher
1446

1547
steps:
16-
- uses: actions/checkout@v2
17-
- name: Set up Python
18-
uses: actions/setup-python@v2
19-
with:
20-
python-version: '3.x'
21-
- name: Install dependencies
22-
run: |
23-
python -m pip install --upgrade pip
24-
pip install setuptools wheel twine
25-
- name: Build and publish
26-
env:
27-
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
28-
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
29-
run: |
30-
python setup.py sdist bdist_wheel
31-
twine upload dist/*
48+
- uses: actions/checkout@v4
49+
50+
- uses: actions/setup-python@v5
51+
with:
52+
python-version: "3.13"
53+
cache: pip
54+
55+
- name: Install build tools
56+
run: pip install build twine
57+
58+
- name: Build distribution
59+
run: python -m build
60+
61+
- name: Check distribution metadata
62+
run: twine check dist/*
63+
64+
- name: Publish to PyPI
65+
uses: pypa/gh-action-pypi-publish@release/v1
66+
# Uncomment the next line to use an API token instead of Trusted Publisher:
67+
# with:
68+
# password: ${{ secrets.PYPI_API_TOKEN }}
Lines changed: 68 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,78 @@
1-
# This workflows will upload a Python Package using Twine when a release is created
2-
# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
1+
# Publishes the package to TestPyPI to smoke-test the publish pipeline.
2+
#
3+
# Triggers:
4+
# • Every push to master (validates the pipeline continuously; existing
5+
# versions are skipped so repeated pushes with the same version are safe).
6+
# • Manual dispatch from the Actions tab (workflow_dispatch).
7+
#
8+
# Authentication: uses TestPyPI Trusted Publisher (OIDC). Configure a
9+
# Trusted Publisher for this repo on test.pypi.org first:
10+
# https://docs.pypi.org/trusted-publishers/adding-a-publisher/
11+
#
12+
# If you prefer an API token instead, remove the `environment` + `permissions`
13+
# blocks and uncomment:
14+
# password: ${{ secrets.TESTPYPI_API_TOKEN }}
15+
# in the "Publish" step below.
316

417
name: Python Client - Publish to TestPyPI
518

619
on:
7-
release:
8-
types: [created]
20+
push:
21+
branches: [master]
22+
workflow_dispatch:
923

1024
jobs:
11-
deploy:
25+
test:
26+
name: "Test before publish"
27+
runs-on: ubuntu-latest
28+
29+
steps:
30+
- uses: actions/checkout@v4
31+
32+
- uses: actions/setup-python@v5
33+
with:
34+
python-version: "3.13"
35+
cache: pip
36+
37+
- name: Install dependencies
38+
run: pip install -e ".[dev]"
39+
40+
- name: Test with pytest
41+
run: pytest
1242

43+
publish:
44+
name: "Build and publish to TestPyPI"
1345
runs-on: ubuntu-latest
46+
needs: test
47+
48+
environment: testpypi
49+
permissions:
50+
id-token: write # required for OIDC Trusted Publisher
1451

1552
steps:
16-
- uses: actions/checkout@v2
17-
- name: Set up Python
18-
uses: actions/setup-python@v2
19-
with:
20-
python-version: '3.x'
21-
- name: Install dependencies
22-
run: |
23-
python -m pip install --upgrade pip
24-
pip install setuptools wheel twine
25-
- name: Build and publish
26-
env:
27-
TWINE_USERNAME: ${{ secrets.TESTPYPI_USERNAME }}
28-
TWINE_PASSWORD: ${{ secrets.TESTPYPI_PASSWORD }}
29-
run: |
30-
python setup.py sdist bdist_wheel
31-
twine upload -r testpypi dist/*
53+
- uses: actions/checkout@v4
54+
55+
- uses: actions/setup-python@v5
56+
with:
57+
python-version: "3.13"
58+
cache: pip
59+
60+
- name: Install build tools
61+
run: pip install build twine
62+
63+
- name: Build distribution
64+
run: python -m build
65+
66+
- name: Check distribution metadata
67+
run: twine check dist/*
68+
69+
- name: Publish to TestPyPI
70+
uses: pypa/gh-action-pypi-publish@release/v1
71+
with:
72+
repository-url: https://test.pypi.org/legacy/
73+
skip-existing: true # same version from repeated master pushes is harmless
74+
# Uncomment the next line to use an API token instead of Trusted Publisher:
75+
# with:
76+
# repository-url: https://test.pypi.org/legacy/
77+
# password: ${{ secrets.TESTPYPI_API_TOKEN }}
78+
# skip-existing: true
Lines changed: 55 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,68 @@
1-
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
2-
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
1+
# Runs on every push / pull-request against master.
2+
# Matrix: Python 3.10 – 3.13 | type-check (mypy) + tests (pytest) + coverage
33

44
name: Python Client - CI
55

66
on:
77
push:
8-
branches: [ master ]
8+
branches: [master]
99
pull_request:
10-
branches: [ master ]
10+
branches: [master]
1111

1212
jobs:
13-
build:
14-
13+
test:
14+
name: "Test · Python ${{ matrix.python-version }}"
1515
runs-on: ubuntu-latest
16+
1617
strategy:
18+
fail-fast: false
1719
matrix:
18-
python-version: [3.6, 3.7, 3.8]
20+
python-version: ["3.10", "3.11", "3.12", "3.13"]
1921

2022
steps:
21-
- uses: actions/checkout@v2
22-
- name: Set up Python ${{ matrix.python-version }}
23-
uses: actions/setup-python@v2
24-
with:
25-
python-version: ${{ matrix.python-version }}
26-
- name: Install dependencies
27-
run: |
28-
python -m pip install --upgrade pip
29-
pip install flake8 pytest
30-
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
31-
- name: Lint with flake8
32-
run: |
33-
# stop the build if there are Python syntax errors or undefined names
34-
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
35-
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
36-
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
37-
- name: Test with pytest
38-
run: |
39-
pytest
40-
- name: Upload Codecov
41-
run: |
42-
bash <(curl -s https://codecov.io/bash)
23+
- uses: actions/checkout@v4
24+
25+
- name: "Set up Python ${{ matrix.python-version }}"
26+
uses: actions/setup-python@v5
27+
with:
28+
python-version: ${{ matrix.python-version }}
29+
cache: pip
30+
31+
- name: Install dependencies
32+
run: pip install -e ".[dev]"
33+
34+
- name: Type-check (mypy)
35+
run: mypy
36+
37+
- name: Test with pytest
38+
run: pytest --cov-report=xml
39+
40+
- name: Upload coverage to Codecov
41+
if: matrix.python-version == '3.13'
42+
uses: codecov/codecov-action@v4
43+
with:
44+
token: ${{ secrets.CODECOV_TOKEN }}
45+
files: coverage.xml
46+
fail_ci_if_error: false
47+
48+
build:
49+
name: "Verify build"
50+
runs-on: ubuntu-latest
51+
needs: test
52+
53+
steps:
54+
- uses: actions/checkout@v4
55+
56+
- uses: actions/setup-python@v5
57+
with:
58+
python-version: "3.13"
59+
cache: pip
60+
61+
- name: Install build tools
62+
run: pip install build twine
63+
64+
- name: Build distribution
65+
run: python -m build
66+
67+
- name: Check distribution metadata
68+
run: twine check dist/*
Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,60 @@
1+
# Installs the published package from PyPI on a weekly schedule and runs a
2+
# quick smoke test to catch any packaging or import regressions.
3+
#
4+
# Matrix: tests the three latest supported Python versions.
5+
16
name: Python Client - Dependency Test
27

38
on:
49
schedule:
5-
- cron: '*/59 * * * *'
10+
- cron: "0 6 * * 1" # every Monday at 06:00 UTC
11+
workflow_dispatch:
612

713
jobs:
8-
build:
9-
14+
smoke-test:
15+
name: "Smoke test · Python ${{ matrix.python-version }}"
1016
runs-on: ubuntu-latest
17+
1118
strategy:
19+
fail-fast: false
1220
matrix:
13-
python-version: [3.6, 3.7, 3.8]
21+
python-version: ["3.11", "3.12", "3.13"]
1422

1523
steps:
16-
- name: Set up Python ${{ matrix.python-version }}
17-
uses: actions/setup-python@v2
18-
with:
19-
python-version: ${{ matrix.python-version }}
20-
- name: Install dependencies
21-
run: |
22-
python -m pip install --upgrade pip
23-
pip install netlicensing-client
24+
- uses: actions/checkout@v4
25+
26+
- name: "Set up Python ${{ matrix.python-version }}"
27+
uses: actions/setup-python@v5
28+
with:
29+
python-version: ${{ matrix.python-version }}
30+
31+
- name: Install published package from PyPI
32+
run: pip install --upgrade netlicensing-client
33+
34+
- name: Verify package imports and version
35+
run: |
36+
python - <<'EOF'
37+
import netlicensing
38+
from netlicensing import (
39+
NetLicensingClient,
40+
NetLicensingConfig,
41+
NetLicensingError,
42+
NetLicensingHTTPError,
43+
NetLicensingAuthError,
44+
Product,
45+
Licensee,
46+
ValidationResult,
47+
LicenseType,
48+
LicensingModel,
49+
)
50+
print(f"netlicensing-client {netlicensing.__version__} imported successfully")
51+
EOF
52+
53+
- name: Verify client instantiation (no network call)
54+
run: |
55+
python - <<'EOF'
56+
from netlicensing import NetLicensingClient
57+
client = NetLicensingClient(api_key="dummy-key")
58+
assert client.config.api_key == "dummy-key"
59+
print("NetLicensingClient instantiated OK")
60+
EOF

0 commit comments

Comments
 (0)