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 :
@@ -45,37 +52,84 @@ jobs:
4552 - name : Checkout
4653 uses : actions/checkout@v3
4754 with :
55+ # Need this to get version number from last tag
4856 fetch-depth : 0
4957
50- - name : Setup python ${{ matrix.python }}
51- uses : actions/setup-python@v4
58+ - name : Install python packages
59+ uses : ./.github/ actions/install_requirements
5260 with :
53- python-version : ${{ matrix.python }}
61+ python_version : ${{ matrix.python }}
62+ requirements_file : requirements-test-${{ matrix.os }}-${{ matrix.python }}.txt
63+ install_options : ${{ matrix.install }}
5464
55- - name : Install with latest dependencies
56- run : pip install .[dev]
65+ - name : List dependency tree
66+ run : pipdeptree
5767
5868 - name : Run tests
59- run : pytest tests
69+ run : pytest
6070
6171 - name : Upload coverage to Codecov
6272 uses : codecov/codecov-action@v3
6373 with :
6474 name : ${{ matrix.python }}/${{ matrix.os }}
6575 files : cov.xml
6676
67- container :
77+ dist :
6878 if : github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository
79+ runs-on : " ubuntu-latest"
80+
81+ steps :
82+ - name : Checkout
83+ uses : actions/checkout@v3
84+ with :
85+ # Need this to get version number from last tag
86+ fetch-depth : 0
87+
88+ - name : Build sdist and wheel
89+ run : |
90+ export SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct) && \
91+ pipx run build
92+
93+ - name : Upload sdist and wheel as artifacts
94+ uses : actions/upload-artifact@v3
95+ with :
96+ name : dist
97+ path : dist
98+
99+ - name : Check for packaging errors
100+ run : pipx run twine check dist/*
101+
102+ - name : Install python packages
103+ uses : ./.github/actions/install_requirements
104+ with :
105+ python_version : ${{env.CONTAINER_PYTHON}}
106+ requirements_file : requirements.txt
107+ install_options : dist/*.whl
108+
109+ - name : Test module --version works using the installed wheel
110+ # If more than one module in src/ replace with module name to test
111+ run : python -m $(ls src | head -1) --version
112+
113+ container :
114+ needs : [lint, dist, test]
69115 runs-on : ubuntu-latest
116+
70117 permissions :
71118 contents : read
72119 packages : write
73120
74121 steps :
75122 - name : Checkout
76123 uses : actions/checkout@v3
124+
125+ # image names must be all lower case
126+ - name : Generate image repo name
127+ run : echo IMAGE_REPOSITORY=ghcr.io/$(tr '[:upper:]' '[:lower:]' <<< "${{ github.repository }}") >> $GITHUB_ENV
128+
129+ - name : Download wheel and lockfiles
130+ uses : actions/download-artifact@v3
77131 with :
78- fetch-depth : 0
132+ path : .devcontainer
79133
80134 - name : Log in to GitHub Docker Registry
81135 if : github.event_name != 'pull_request'
@@ -89,74 +143,45 @@ jobs:
89143 id : meta
90144 uses : docker/metadata-action@v4
91145 with :
92- images : ghcr.io/ ${{ github.repository }}
146+ images : ${{ env.IMAGE_REPOSITORY }}
93147 tags : |
94- type=ref,event=branch
95148 type=ref,event=tag
149+ type=raw,value=latest
96150
97151 - name : Set up Docker Buildx
98152 id : buildx
99153 uses : docker/setup-buildx-action@v2
100154
101- - name : Build developer image for testing
102- uses : docker/build-push-action@v3
103- with :
104- tags : build:latest
105- context : .
106- target : build
107- load : true
108-
109- - name : Run tests in the container locked with requirements_dev.txt
110- run : |
111- docker run --name test build bash /project/.github/workflows/container_tests.sh
112- docker cp test:/project/dist .
113- docker cp test:/project/lockfiles .
114- docker cp test:/project/cov.xml .
115-
116- - name : Upload coverage to Codecov
117- uses : codecov/codecov-action@v3
118- with :
119- name : 3.10-locked/ubuntu-latest
120- files : cov.xml
121-
122155 - name : Build runtime image
123156 uses : docker/build-push-action@v3
124157 with :
125- push : ${{ github.event_name != 'pull_request' }}
158+ build-args : |
159+ PIP_OPTIONS=-r lockfiles/requirements.txt dist/*.whl
160+ push : ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags') }}
161+ load : ${{ ! (github.event_name == 'push' && startsWith(github.ref, 'refs/tags')) }}
126162 tags : ${{ steps.meta.outputs.tags }}
127- context : .
128- labels : ${{ steps.meta.outputs.labels }}
163+ context : .devcontainer
164+ # If you have a long docker build, uncomment the following to turn on caching
165+ # For short build times this makes it a little slower
166+ # cache-from: type=gha
167+ # cache-to: type=gha,mode=max
129168
130169 - name : Test cli works in runtime image
131- # check that the first tag can run with --version parameter
132- run : docker run $(echo ${{ steps.meta.outputs.tags }} | head -1) --version
133-
134- - name : Test cli works in sdist installed in local python
135- # ${GITHUB_REPOSITORY##*/} is the repo name without org
136- # Replace this with the cli command if different to the repo name
137- run : pip install dist/*.gz && ${GITHUB_REPOSITORY##*/} --version
138-
139- - name : Upload build files
140- uses : actions/upload-artifact@v3
141- with :
142- name : dist
143- path : dist
144-
145- - name : Upload lock files
146- uses : actions/upload-artifact@v3
147- with :
148- name : lockfiles
149- path : lockfiles
170+ run : docker run ${{ env.IMAGE_REPOSITORY }} --version
150171
151172 release :
152173 # upload to PyPI and make a release on every tag
153- if : github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
154- needs : container
174+ needs : [lint, dist, test]
175+ if : ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags') }}
155176 runs-on : ubuntu-latest
156177
157178 steps :
158179 - uses : actions/download-artifact@v3
159180
181+ - name : Fixup blank lockfiles
182+ # Github release artifacts can't be blank
183+ run : for f in lockfiles/*; do [ -s $f ] || echo '# No requirements' >> $f; done
184+
160185 - name : Github Release
161186 # We pin to the SHA, not the tag, for security reasons.
162187 # https://docs.github.com/en/actions/learn-github-actions/security-hardening-for-github-actions#using-third-party-actions
0 commit comments