1- # Workflow for publishing into pyPI
1+ # Workflow for CI + semantic-release + publish to TestPyPI (build from the release tag)
22
3- name : ci-cd
3+ name : ci-cd
44
55on :
66 push :
77 branches : [ main ]
8- tags :
9- - " *.*.*"
108 pull_request :
119 branches : [ main ]
1210 workflow_dispatch :
1311
1412jobs :
1513 ci :
16- # Set up operating system
1714 runs-on : ubuntu-latest
18-
15+
1916 strategy :
2017 matrix :
2118 python-version : ['3.10', '3.11', '3.12', '3.13']
2219
23- # Steps represent a sequence of tasks that will be executed as
24- # part of the job
2520 steps :
26- # Checks-out your repository so your job can access it
2721 - name : Check-out repository
28- uses : actions/checkout@v2
22+ uses : actions/checkout@v4
2923
30- # Set up Python
3124 - name : Set up Python ${{ matrix.python-version }}
32- uses : actions/setup-python@v4
25+ uses : actions/setup-python@v5
3326 with :
3427 python-version : ${{ matrix.python-version }}
3528
36- # Install dependencies
3729 - name : Install dependencies
3830 run : |
3931 python -m pip install --upgrade pip
4032 pip install -e .[tests]
4133
42- # Run pytest with coverage
4334 - name : Run tests with coverage
4435 run : |
4536 pytest --cov=dumbpy --cov-branch --cov-report=xml
46-
47- # Badge
37+
4838 - name : Upload coverage reports to Codecov
4939 uses : codecov/codecov-action@v5
5040 with :
@@ -55,12 +45,16 @@ jobs:
5545 needs : ci
5646 permissions :
5747 contents : write
58- if : github.event_name == 'push' && (github.ref == 'refs/heads/main')
48+ if : github.event_name == 'push' && github.ref == 'refs/heads/main'
49+
50+ outputs :
51+ released_tag : ${{ steps.semrel.outputs.released_tag }}
5952
6053 steps :
6154 - uses : actions/checkout@v4
6255 with :
6356 fetch-depth : 0
57+ fetch-tags : true
6458
6559 - uses : actions/setup-python@v5
6660 with :
@@ -76,45 +70,67 @@ jobs:
7670 git config user.name "github-actions[bot]"
7771 git config user.email "github-actions[bot]@users.noreply.github.com"
7872
79- - name : Semantic version bump + tag
73+ # Creates the release commit + tag (and pushes them).
74+ # Then we read the "last released tag" and expose it as an output for the cd job.
75+ - name : Semantic version bump + tag (and export tag)
76+ id : semrel
8077 env :
8178 GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
82- run :
79+ shell : bash
80+ run : |
81+ set -euo pipefail
82+
83+ BEFORE="$(semantic-release version --print-last-released-tag 2>/dev/null || true)"
84+ echo "Last released tag before: ${BEFORE:-<none>}"
85+
8386 semantic-release version --no-changelog --skip-build --no-vcs-release
8487
88+ AFTER="$(semantic-release version --print-last-released-tag 2>/dev/null || true)"
89+ echo "Last released tag after: ${AFTER:-<none>}"
8590
91+ # Only publish if a new tag was actually created
92+ if [[ -n "${AFTER}" && "${AFTER}" != "${BEFORE}" ]]; then
93+ echo "released_tag=${AFTER}" >> "$GITHUB_OUTPUT"
94+ else
95+ echo "released_tag=" >> "$GITHUB_OUTPUT"
96+ echo "No new release created (no version bump)."
97+ fi
8698
8799 cd :
88-
89- # Set up operating system
90100 runs-on : ubuntu-latest
101+ needs : release
91102
92103 permissions :
93104 id-token : write
94- contents : write
95- # Only run this job if the "ci" job passes
96- needs : release
105+ contents : read
97106
98- # Only run this job if new work is pushed to "main" or "dev"
99- if : github.event_name == 'push' && (github.ref == 'refs/heads/main')
107+ # Only run if release created a new tag
108+ if : needs.release.outputs.released_tag != ''
100109
101- # Define job steps
102110 steps :
103- - name : Check-out repository
104- uses : actions/checkout@v3
111+ - name : Check-out released tag
112+ uses : actions/checkout@v4
105113 with :
106114 fetch-depth : 0
107-
115+ fetch-tags : true
116+ ref : ${{ needs.release.outputs.released_tag }}
117+
108118 - name : Set up Python 3.12
109- uses : actions/setup-python@v4
119+ uses : actions/setup-python@v5
110120 with :
111- python-version : 3.12
121+ python-version : " 3.12"
112122
113- # Install dependencies
114- - name : Install dependencies
123+ - name : Install build tooling
115124 run : |
116125 python -m pip install --upgrade pip
117- pip install -e .[dev]
126+ pip install hatch
127+
128+ - name : Show git/tag info (sanity check)
129+ shell : bash
130+ run : |
131+ git status --porcelain
132+ git describe --tags --always || true
133+ python -c "import pathlib; print(pathlib.Path('.').resolve())"
118134
119135 - name : Hatch build locally
120136 run : hatch build
@@ -126,18 +142,14 @@ jobs:
126142 password : ${{ secrets.TEST_PYPI_API_TOKEN }}
127143
128144 testdumbpy :
129-
130- # Set up operating system
131145 runs-on : ubuntu-latest
132-
133146 needs : cd
134147
135148 strategy :
136149 matrix :
137150 python-version : ['3.10', '3.11', '3.12', '3.13']
138-
139- steps :
140151
152+ steps :
141153 - uses : actions/setup-python@v5
142154 with :
143155 python-version : ${{ matrix.python-version }}
@@ -146,9 +158,10 @@ jobs:
146158 run : |
147159 python -m pip install --upgrade pip
148160 pip install \
149- --index-url https://test.pypi.org/simple/ \
150- --extra-index-url https://pypi.org/simple/ \
151- dumbpy
161+ --index-url https://test.pypi.org/simple/ \
162+ --extra-index-url https://pypi.org/simple/ \
163+ dumbpy
152164
153-
154-
165+ - name : Print installed version
166+ run : |
167+ python -c "import dumbpy; print('dumbpy version:', getattr(dumbpy, '__version__', '<no __version__>'))"
0 commit comments