44 push :
55 pull_request :
66 schedule :
7- # Run every Monday at 8am to check latest versions of dependencies
7+ # Run weekly to check latest versions of dependencies
88 - cron : " 0 8 * * WED"
9+ env :
10+ # The target python version, which must match the Dockerfile version
11+ CONTAINER_PYTHON : " 3.11"
912
1013jobs :
1114 lint :
@@ -17,24 +20,28 @@ jobs:
1720 - name : Checkout
1821 uses : actions/checkout@v3
1922
20- - name : Setup python
21- uses : actions/setup-python@v4
23+ - name : Install python packages
24+ uses : ./.github/ actions/install_requirements
2225 with :
23- python-version : " 3.10"
26+ requirements_file : requirements-dev-3.x.txt
27+ install_options : -e .[dev]
2428
2529 - name : Lint
26- run : |
27- touch requirements_dev.txt requirements.txt
28- pip install -r requirements.txt -r requirements_dev.txt -e .[dev]
29- tox -e pre-commit,mypy
30+ run : tox -e pre-commit,mypy
3031
3132 test :
3233 if : github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository
3334 strategy :
3435 fail-fast : false
3536 matrix :
3637 os : ["ubuntu-latest"] # can add windows-latest, macos-latest
37- python : ["3.8", "3.9", "3.10"]
38+ python : ["3.9", "3.10", "3.11"]
39+ install : ["-e .[dev]"]
40+ # Make one version be non-editable to test both paths of version code
41+ include :
42+ - os : " ubuntu-latest"
43+ python : " 3.8"
44+ install : " .[dev]"
3845
3946 runs-on : ${{ matrix.os }}
4047 env :
@@ -50,37 +57,84 @@ jobs:
5057 - name : Checkout
5158 uses : actions/checkout@v3
5259 with :
60+ # Need this to get version number from last tag
5361 fetch-depth : 0
5462
55- - name : Setup python ${{ matrix.python }}
56- uses : actions/setup-python@v4
63+ - name : Install python packages
64+ uses : ./.github/ actions/install_requirements
5765 with :
58- python-version : ${{ matrix.python }}
66+ python_version : ${{ matrix.python }}
67+ requirements_file : requirements-test-${{ matrix.os }}-${{ matrix.python }}.txt
68+ install_options : ${{ matrix.install }}
5969
60- - name : Install with latest dependencies
61- run : pip install .[dev]
70+ - name : List dependency tree
71+ run : pipdeptree
6272
6373 - name : Run tests
64- run : pytest tests
74+ run : pytest
6575
6676 - name : Upload coverage to Codecov
6777 uses : codecov/codecov-action@v3
6878 with :
6979 name : ${{ matrix.python }}/${{ matrix.os }}
7080 files : cov.xml
7181
72- container :
82+ dist :
7383 if : github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository
84+ runs-on : " ubuntu-latest"
85+
86+ steps :
87+ - name : Checkout
88+ uses : actions/checkout@v3
89+ with :
90+ # Need this to get version number from last tag
91+ fetch-depth : 0
92+
93+ - name : Build sdist and wheel
94+ run : |
95+ export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) && \
96+ pipx run build
97+
98+ - name : Upload sdist and wheel as artifacts
99+ uses : actions/upload-artifact@v3
100+ with :
101+ name : dist
102+ path : dist
103+
104+ - name : Check for packaging errors
105+ run : pipx run twine check dist/*
106+
107+ - name : Install python packages
108+ uses : ./.github/actions/install_requirements
109+ with :
110+ python_version : ${{env.CONTAINER_PYTHON}}
111+ requirements_file : requirements.txt
112+ install_options : dist/*.whl
113+
114+ - name : Test module --version works using the installed wheel
115+ # If more than one module in src/ replace with module name to test
116+ run : python -m $(ls src | head -1) --version
117+
118+ container :
119+ needs : [lint, dist, test]
74120 runs-on : ubuntu-latest
121+
75122 permissions :
76123 contents : read
77124 packages : write
78125
79126 steps :
80127 - name : Checkout
81128 uses : actions/checkout@v3
129+
130+ # image names must be all lower case
131+ - name : Generate image repo name
132+ run : echo IMAGE_REPOSITORY=ghcr.io/$(tr '[:upper:]' '[:lower:]' <<< "${{ github.repository }}") >> $GITHUB_ENV
133+
134+ - name : Download wheel and lockfiles
135+ uses : actions/download-artifact@v3
82136 with :
83- fetch-depth : 0
137+ path : .devcontainer
84138
85139 - name : Log in to GitHub Docker Registry
86140 if : github.event_name != 'pull_request'
@@ -94,75 +148,45 @@ jobs:
94148 id : meta
95149 uses : docker/metadata-action@v4
96150 with :
97- images : ghcr.io/ ${{ github.repository }}
151+ images : ${{ env.IMAGE_REPOSITORY }}
98152 tags : |
99- type=ref,event=branch
100153 type=ref,event=tag
154+ type=raw,value=latest
101155
102156 - name : Set up Docker Buildx
103157 id : buildx
104158 uses : docker/setup-buildx-action@v2
105159
106- - name : Build developer image for testing
107- uses : docker/build-push-action@v3
108- with :
109- tags : build:latest
110- context : .
111- target : build
112- load : true
113-
114- - name : Run tests in the container locked with requirements_dev.txt
115- run : |
116- docker run --name test build bash /project/.github/workflows/container_tests.sh
117- docker cp test:/project/dist .
118- docker cp test:/project/lockfiles .
119- docker cp test:/project/cov.xml .
120-
121- - name : Upload coverage to Codecov
122- uses : codecov/codecov-action@v3
123- with :
124- name : 3.10-locked/ubuntu-latest
125- files : cov.xml
126-
127160 - name : Build runtime image
128161 uses : docker/build-push-action@v3
129162 with :
130- push : ${{ github.event_name != 'pull_request' }}
163+ build-args : |
164+ PIP_OPTIONS=-r lockfiles/requirements.txt dist/*.whl
165+ push : ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags') }}
166+ load : ${{ ! (github.event_name == 'push' && startsWith(github.ref, 'refs/tags')) }}
131167 tags : ${{ steps.meta.outputs.tags }}
132- context : .
133- labels : ${{ steps.meta.outputs.labels }}
168+ context : .devcontainer
169+ # If you have a long docker build, uncomment the following to turn on caching
170+ # For short build times this makes it a little slower
171+ # cache-from: type=gha
172+ # cache-to: type=gha,mode=max
134173
135174 - name : Test cli works in runtime image
136- # check that the first tag can run with --version parameter
137- run : docker run $(echo ${{ steps.meta.outputs.tags }} | head -1) --version
138-
139- - name : Test cli works in sdist installed in local python
140- # ${GITHUB_REPOSITORY##*/} is the repo name without org
141- # Replace this with the cli command if different to the repo name
142- # (python3-pip-skeleton-cli replaces this with python3-pip-skeleton)
143- run : pip install dist/*.gz && python3-pip-skeleton --version
144-
145- - name : Upload build files
146- uses : actions/upload-artifact@v3
147- with :
148- name : dist
149- path : dist
150-
151- - name : Upload lock files
152- uses : actions/upload-artifact@v3
153- with :
154- name : lockfiles
155- path : lockfiles
175+ run : docker run ${{ env.IMAGE_REPOSITORY }} --version
156176
157177 release :
158178 # upload to PyPI and make a release on every tag
159- if : github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
160- needs : container
179+ needs : [lint, dist, test]
180+ if : ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags') }}
161181 runs-on : ubuntu-latest
162182
163183 steps :
164184 - uses : actions/download-artifact@v3
165185
186+ - name : Fixup blank lockfiles
187+ # Github release artifacts can't be blank
188+ run : for f in lockfiles/*; do [ -s $f ] || echo '# No requirements' >> $f; done
189+
166190 - name : Github Release
167191 # We pin to the SHA, not the tag, for security reasons.
168192 # https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions
0 commit comments